【问题标题】:React Native blob/file is not getting to the serverReact Native blob/文件没有到达服务器
【发布时间】:2022-06-12 08:47:09
【问题描述】:

我非常卡在这里。我不知道我做错了什么。我正在尝试将文件从expo-image-picker component 发送到服务器。表单已发送,但图像未发送。 fetch 命令立即给出“网络请求失败”错误。服务器确实收到了请求,但没有附加图像。

更多信息:

  • 我正在创建表单数据对象并将 blob 附加到它。我也尝试过使用FormData.append("image", {uri, name: 'filename', type: 'image/filetype'}) 进行此操作,大多数文章建议的方式,忽略 TS 错误,但它也失败了。

  • 我没有提交给 AWS 或 Firebase,所以我没有使用这些库,无论如何我看不出他们在做什么与我有什么不同。

  • 我没有为此设置任何特定权限。我确实看到一些文章谈论上传权限,但他们已经超过 5 年,并且在 android 5.0 之前谈论。

这是我用来提交的函数。 pathToImage 从 ImagePicker 返回。

const fetchImageFromUri = async (uri: string) => {
  try {
    const response = await fetch(uri);
    const blob = await response.blob();

    return blob;
  } catch (error) {
    console.log("fetchImageFromUri error:", error);
    throw new Error("fetchImageFromUri");
  }
};

const upload = async () => {
  setMessage("");
  setErrMessage("");

  if (pathToImage != null) {
    const fileToUpload = await fetchImageFromUri(pathToImage);

    const formData = new FormData();
    formData.append("action", "Image Upload");
    formData.append("image", fileToUpload, "filename");

    // from: https://stackoverflow.com/questions/71198201/react-native-unable-to-upload-file-to-server-network-request-failed
    // most articles say this is the way to upload the file... Typescript gives an error
    // because it only wants type 'string | Blob'
    // let uriParts = pathToImage.split(".");
    // let fileType = uriParts[uriParts.length - 1];
    // formData.append("image", {
    //   uri: pathToImage,
    //   name: `photo.${fileType}`,
    //   type: `image/${fileType}`,
    // });

    // create the header options
    const options: RequestInit = {
      method: "POST",
      body: formData,
      headers: {
        "Content-Type": "multipart/form-data",
        Accept: "image/jpeg, image/png",
      },
    };

    try {
      const res = await fetch(URL, options);
            
      console.log("fetch returned"); // this line is never reached
            
      if (!res.ok) {
        throw new Error("Something went wrong");
      }

      const body = (await res.json()) as any;
            
      if (body.code > 200) {
        setErrMessage(body.msg);
      } else {
        setMessage(body.msg);
      }
    } catch (err: any) {
      setErrMessage("There was an error in upload");
      console.log("upload catch error:", err.message);
    }
  }
};

完整代码可以在我的GitHub repository找到。

【问题讨论】:

标签: typescript react-native expo fetch-api


【解决方案1】:

感谢 Brandonjgs 为我指明了正确的方向。我能够解决问题。

这是新的上传功能。

const upload = async () => {
    console.log("\n***** Upload Image *****");
    setMessage("");
    setErrMessage("");
    setLoading(true);

    if (pathToImage) {
        console.log("***** get other fields section *****");
        const dataToSend: Record<string, string> = {};
        dataToSend["action"] = "Image Upload";

        console.log("***** Options section *****");
        const options: FileSystemUploadOptions = {
            headers: {
                "Content-Type": "multipart/form-data",
                Accept: "image/jpeg, image/png",
            },
            httpMethod: "POST",
            uploadType: FileSystemUploadType.MULTIPART,
            fieldName: "image",
            parameters: dataToSend,
        };

        console.log("***** 'Fetch' section *****");
        try {
            const response = await FileSystem.uploadAsync(
                URL,
                pathToImage,
                options
            );

            setLoading(false);

            if (response.status >= 200 && response.status < 300) {
                const body = JSON.parse(response.body);
                setMessage(body.msg);
            } else {
                setErrMessage(`${response.status} Error: ${response.body}`);
            }
        } catch (err: any) {
            console.error(err);
            setErrMessage(err.message);
        }
    }
};

请务必查看 FileSystem.uploadAsync 文档。它不返回标准的 http 响应,它自己格式化并返回:

  • status:错误代码
  • header:服务器返回的http头
  • body:无论服务器“发回”什么——就我而言,它是 JSON。请注意,如果服务器没有响应或者它是一个错误的 URL,它会返回一个 HTML 错误页面,而不是标准的错误消息字符串(我发现这是一个奇怪的选择,因为这是本机反应,我不一定要导航到一个新的当我上传页面时,我会在状态对象中捕获字符串以发布响应)。

【讨论】:

    猜你喜欢
    • 2016-06-27
    • 2019-11-04
    • 2019-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-28
    • 1970-01-01
    • 2020-12-04
    相关资源
    最近更新 更多