Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[expo-file-system][android] Fix uploadAsync signature and cast exception #9076

Merged

Conversation

lukmccall
Copy link
Contributor

Why

Fixes #9075

How

  • Fix incorrect uploadAsync signature
  • Fix java.lang.Double cannot be cast to java.lang.Integer

Test Plan

  • tested using simple demo from documentation ✅

@github-actions
Copy link
Contributor

github-actions bot commented Jul 3, 2020

Native Component List for this branch is ready

Copy link
Contributor

@bbarthec bbarthec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍 Never slowing down with number of PRs opened per workday, eh? 😅

@lukmccall lukmccall merged commit fffb060 into master Jul 6, 2020
@lukmccall lukmccall deleted the @lukmccall/expo-file-system/fix-upload-async-on-android branch July 6, 2020 09:13
@NeOMakinG
Copy link

Will this PR be inside a patch release ? It's currently blocking the use of this new module for the whole version 38 ? Maybe it's already inside a patch, but can't find changelogs for 38.0.x versions !

@lukmccall
Copy link
Contributor Author

I'm sorry for the late replay. Unofortynetly it wasn't published. I don't know if we will release a patch for 38. But if we do it, this fix should be also included. For now, as a workaround, you can use the fetch function on Android.

@NeOMakinG
Copy link

Yep, already what I did when I seen this wrong signature, but having to handle one way on android and another way on iOS is a bit dirty, can't wait to use this :)

Thanks for the reply, np man I know what is it to work on an open source project :)

@r-mhjn
Copy link

r-mhjn commented Aug 1, 2020

Hey @NeOMakinG could you please share how you used fetch to actually handle the file upload (In background)
? I don't know about it. @lukmccall
Thanks for the fix, any idea so as to when it would be published.

@NeOMakinG
Copy link

NeOMakinG commented Aug 1, 2020

Hey @r-mhjn

This is basically something like this : where firstPicture.uri is the local path of the picture.

                    const formData = new FormData();

                    formData.append('files', {
                        uri: firstPicture.uri,
                        name: `photo1.jpg`,
                        type: `image/jpg`,
                    });

                    formData.append('files', {
                        uri: secondPicture.uri,
                        name: `photo2.jpg`,
                        type: `image/jpg`,
                    });

                    const response = await fetch(`${constants.backend}upload`, {
                        method: 'POST',
                        body: formData,
                    });

                    await response.text();

By the way, I don't do it on background yet, which means that if users put the app on background, the upload is aborted (and this is why uploadAsync is way more easy to use than setting up a background task with fetch)

@r-mhjn
Copy link

r-mhjn commented Aug 1, 2020

@NeOMakinG thanks alot mate, i think using this along with background fetch would do the job for me

@qzlu-cyber
Copy link

@NeOMakinG I also encountered this problem on Android, and then I used the fatch to send pictures to the backend according to your method. I want to save the image in the backend, I used the createwritestream in Node.js, but it has been unsuccessful. The size of the saved images is 0kb. Can you help me, please? Thank you very much! This is my code:
app.post("/android", (req, res) => { req.pipe( fs.createWriteStream("./public/uploads/avatars/image" + Date.now() + ".png") ); });

@r-mhjn
Copy link

r-mhjn commented Aug 7, 2020

@NeOMakinG Hi neo, where you able to set the api as a background task, as well so it does not abort when the app is back-grounded, i tried to do so but does'nt seem to be working,
let taskName =upload-project-data-${projectName} TaskManager.defineTask(taskName, async () => { try { const receivedNewData = await Axios.post(${endpoint}, formData, { headers: headers }, config) console.log(receivedNewData) return receivedNewData ? BackgroundFetch.Result.NewData : BackgroundFetch.Result.NoData; } catch (error) { return BackgroundFetch.Result.Failed; } });
this is how im doing it.

@NeOMakinG
Copy link

Never tried to do add it to a backgroundTask, as I seen that uploadAsync was coming and globally it seems that my users read the "Loading, don't quit the app" :/

Did you test on a standalone app ? I think backgroundTasks are not working on anything else than a standalone app!

@r-mhjn
Copy link

r-mhjn commented Aug 7, 2020

Oh damn, no i haven't tried it in a stand alone app, i create this app through normal expo init,
User probabaly wont like to wait im my case, as user will be uploading atleast 500mb data, maybe less but the max limit will be atleast around 500mb to 1 gb

@NeOMakinG
Copy link

NeOMakinG commented Aug 7, 2020

https://docs.expo.io/versions/v38.0.0/sdk/task-manager/

It looks like background mode works on Expo for Android, but not on iOS, except on standalone apps

@r-mhjn
Copy link

r-mhjn commented Aug 7, 2020

I see the fix has been merged nearly a month ago i hope they publish it soon

@r-mhjn
Copy link

r-mhjn commented Aug 7, 2020

Yeah @NeOMakinG i got the code from the same documentation
Am i using the right API?
Looks like i just defined the task and did not register it with backgroud fetch

@NeOMakinG
Copy link

NeOMakinG commented Aug 7, 2020

Unfortunately, I don't know at all :(

Never faced it yet, but this looks designed to launch periodical tasks while the app is backgrounded, but not implicitly "launch a piece of code which will be executed even if the app is backgrounded", so maybe you can manage to do this with it..

@NeOMakinG
Copy link

I see the fix has been merged nearly a month ago i hope they publish it soon

Expo has been updated from 38.0.8 to 38.0.9 7 days ago, maybe the fix is inside this patch :)

@r-mhjn
Copy link

r-mhjn commented Aug 7, 2020

Just a second ill check my sdk version

@r-mhjn
Copy link

r-mhjn commented Aug 7, 2020

Yes exactly, i feel the same

@r-mhjn
Copy link

r-mhjn commented Aug 7, 2020

Im on sdk 38.0.0 damn , looks like time to upgrade

@lukmccall
Copy link
Contributor Author

I think it wasn't added to this patch :/

@r-mhjn
Copy link

r-mhjn commented Aug 7, 2020

oh damn y so, its been a trouble for weeks, thanks for intimating @lukmccall,
i just ran expo upgrade tho and my sdk version checked from 38.0.0 to 38.0.2
@NeOMakinG how did you get 38.0.9?

@NeOMakinG
Copy link

https://www.npmjs.com/package/expo

Just looked there, didn't upgrade yet, but I think I upgraded to 38.0.8 some weeks ago

@r-mhjn
Copy link

r-mhjn commented Aug 7, 2020

Should i try something like expo upgrade@latest or version?
Oops thats not a valid command, don' t know why i didn't get the latest on expo upgrade

@shashwat-kalpvaig
Copy link

I am still facing the same issue on Andorid (11) with SDK 42.0.1. I want to read the file using readAsStringAync but it throws

Error: Location 'file:///data/user/0/host.exp.exponent/cache/ExperienceData/%4050shashwat%2FATranZ_B/DocumentPicker/e6cf5144-b36f-48df-b6db-5ce277a069cb.jpg' isn't readable.

@gasparnd
Copy link

Same problem that @50shashwat I take the video from ImagePicker

import React, { useEffect, useState } from "react";
import { Alert, Pressable, StyleSheet, Text, View } from "react-native";
import * as ImagePicker from "expo-image-picker";
import * as FileSystem from "expo-file-system";
import { FileSystemUploadType } from "expo-file-system";
import Video from "./components/Video";

export default function App() {
  const [video, setVideo] = useState<string>("");

  const getPermissions = async () => {
    try {
      const library = await ImagePicker.requestMediaLibraryPermissionsAsync();

      if (!library.granted) {
        Alert.alert("Ups!", "We need permision for this action");
        return;
      }

      searchVideo();
    } catch (err) {}
  };

  const searchVideo = async () => {
    const res = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.Videos,
    });

    if (!res.cancelled) {
      setVideo(res.uri);
    }
  };

  const handelUploade = async (uri: string) => {
    try {
      const videoUri = uri.split("///").join("//");
      console.log(
        "🚀 ~ file: App.tsx ~ line 37 ~ handelUploade ~ videoUri",
        videoUri
      );
      const headers = {
        Accept: "application/json",
        "Content-Type": "multipart/form-data",
      };

      const res = await FileSystem.uploadAsync(
        "https://e1ba-190-211sfdsf-90-90.ngrok.io/uploadVideo",
        uri,
        {
          httpMethod: "POST",
          uploadType: FileSystemUploadType.MULTIPART,
          fieldName: "file",
          headers: headers,
        }
      );

      if (res) {
        return res;
      }
    } catch (error) {
      console.log(
        "🚀 ~ file: App.tsx ~ line 49 ~ handelUploade ~ error",
        error
      );
      Alert.alert("Somthing is wrong");
    }
  };

  return (
    <View style={styles.container}>
      {video && <Video uri={video} />}

      <Pressable
        onPress={() => (!video ? getPermissions() : handelUploade(video))}
        style={[styles.primaryButton, { marginVertical: "3%" }]}
      >
        <Text style={styles.buttonText}>
          {!video ? "Select video" : "Upload video"}
        </Text>
      </Pressable>
      {video && (
        <Pressable onPress={searchVideo} style={styles.secondaryButton}>
          <Text style={styles.buttonText}>Select other video</Text>
        </Pressable>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    padding: "5%",
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
  buttonText: {
    fontSize: 20,
    fontWeight: "500",
  },
  primaryButton: {
    justifyContent: "center",
    alignItems: "center",
    width: "100%",
    backgroundColor: "#00ED64",
    borderWidth: 1,
    borderColor: "transparent",
    borderRadius: 10,
    paddingVertical: 10,
    paddingHorizontal: 40,
  },
  secondaryButton: {
    justifyContent: "center",
    alignItems: "center",
    width: "100%",
    borderWidth: 2,
    borderColor: "#00ED64",
    borderRadius: 10,
    paddingVertical: 10,
    paddingHorizontal: 40,
  },
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

FileSystem.uploadAsync not working for Android
7 participants