React Native +世博会axios 文件上传无法正常工作,因为 axios 未将表单数据发送到服务器

发布于 2025-01-11 01:38:19 字数 1691 浏览 2 评论 0原文

我正在尝试将带有 React Native 前端和 axios 的图像上传到我的后端。

const pickImage = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.Images,
      allowsEditing: false,
      aspect: [9, 16],
      quality: 1,
    });

    console.log(result.uri);

    if (!result.cancelled) {
      console.log(result);
      setPhoto(result);
    }
  };

现在您可以清楚地看到我正在使用 ImagePicker 库设置照片状态

然后我创建一个表单数据实例:

     let img_to_upload = {  
        type: 'image/jpeg',    
        name: 'random-file-name',  
        uri: Platform.OS === 'android' ? photo.uri : photo.uri.replace('file://', ''),
    };  

    let formData = new FormData();
    formData.append("title", 'this is tandom text');
    formData.append("file", img_to_upload);

在这里您可以清楚地看到我启动了一个表单数据对象,然后向表单添加两个字段。

  1. 最后但并非最不重要
  2. 的一点

是,我将其发送到服务器:

axios({
      method: 'POST',
      url: U_R_L,  
      data: formData,
      transformRequest: (d) => d, 
      headers: { 
        "Content-Type": "multipart/form-data; charset=utf-8; boundary=------random-boundary",
      }
    })
    .then((response) => {
       console.log("response : ");  
       console.log(response.data);    
    }, (error) => {
        console.log("error : "); 
        console.log(error); 
    })
    .then(() => {
      setProgress(false);
    });

但它从不向服务器发送任何文件。

这是错误:

在此处输入图像描述

但是当我使用 REST 客户端测试同一端点时,它可以工作。

I am trying to upload an image with react native front end and axios to my back end.

This is how pic the image

const pickImage = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.Images,
      allowsEditing: false,
      aspect: [9, 16],
      quality: 1,
    });

    console.log(result.uri);

    if (!result.cancelled) {
      console.log(result);
      setPhoto(result);
    }
  };

now you can see clearly that I am setting up the photo state with the ImagePicker library.

Then I create a form data instance:

     let img_to_upload = {  
        type: 'image/jpeg',    
        name: 'random-file-name',  
        uri: Platform.OS === 'android' ? photo.uri : photo.uri.replace('file://', ''),
    };  

    let formData = new FormData();
    formData.append("title", 'this is tandom text');
    formData.append("file", img_to_upload);

here you can see clearly I have initiated a formdata object and then adding two fields to the form.

  1. title
  2. file

And last but not least, I send this to the server:

axios({
      method: 'POST',
      url: U_R_L,  
      data: formData,
      transformRequest: (d) => d, 
      headers: { 
        "Content-Type": "multipart/form-data; charset=utf-8; boundary=------random-boundary",
      }
    })
    .then((response) => {
       console.log("response : ");  
       console.log(response.data);    
    }, (error) => {
        console.log("error : "); 
        console.log(error); 
    })
    .then(() => {
      setProgress(false);
    });

But it never sends any file to the server.

Here is the error:

enter image description here

But when I test the same endpoint with my REST client, it works.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

初雪 2025-01-18 01:38:19

Axios 的 FormData 自 v0.25 起就已被破坏。
他们毫无理由地尝试优化 FormData 检测实用程序。不幸的是,对于非浏览器环境,正确的检测失败。

您现在可以在这里找到解决方法:
https://github.com/axios/axios/issues/4406#issuecomment-1048693170

TL;DR

const formData = new FormData();
...
const response = await axios.post('/URL', formData, {
  headers: {
    'Content-Type': 'multipart/form-data',
  },
  transformRequest: (data, headers) => {
    return formData; // this is doing the trick
  },
});

只需传递一个transformRequest并返回您的formData,一切都会再次神奇地“工作”。不过,这是一个解决方法(我在这个问题上花了 5 个小时),希望在即将发布的版本中得到修复。

Axios' FormData is broken since v0.25 for react-native.
They tried to optimize the FormData detection util for no real reason. Unfortunately, the proper detection fails for non browser environments.

You can find a workaround here for now:
https://github.com/axios/axios/issues/4406#issuecomment-1048693170

TL;DR

const formData = new FormData();
...
const response = await axios.post('/URL', formData, {
  headers: {
    'Content-Type': 'multipart/form-data',
  },
  transformRequest: (data, headers) => {
    return formData; // this is doing the trick
  },
});

Just pass a transformRequest and return your formData and everything will "work" magically again. This is a workaround though (I've spent 5 hours on this issue) and should hopefully be fixed in an upcoming version.

薄荷港 2025-01-18 01:38:19

无需在请求中设置 content-type 标头。它会自动识别您的请求包含缓冲区数据。因此,您只需传递请求而不设置 multipart content-type 标头。

我也对同样的问题感到困惑。我的 MacBook 使用邮递员发送请求没有任何问题,而我的 Android 设备在发送 multipart 请求时遇到问题。

解决方案

网络连接不良是这部分的主要问题。因此,只需将您的移动网络更改为任何其他具有更好互联网连接的网络即可。并再次检查。当然它解决了您的问题

用于发送多部分数据的本机 javascript 查询 - axios 也使用相同的本机库

 var data = new FormData();
    data.append("file", {
                          name: 'image.png',
                          type: 'image/png,
                          uri: 'file:///file-cache-url'
                        }, "image.png");
     
    var xhr = new XMLHttpRequest();
    xhr.withCredentials = true;
    
    xhr.addEventListener("readystatechange", function() {
      if(this.readyState === 4) {
        console.log(this.responseText);
      }
    });

xhr.open("POST", "http://127.0.0.1:3000/data/upload");

xhr.send(data);

there is no no need to set the content-type header in your request. It automatically identify your request contains the buffer data. so you just pass the request without setting multipart content-type header.

I'm also confused with this same issue. my MacBook is sending the request without any issue by using postman, and my android device is having issues sending the multipart request.

Solution

Poor network connection is the major issue in this part. So just change your mobile network to any other network, which has the better internet connectivity. and check again. surely it solved your issue

Native javascript query for sending the multipart data - axios is also using this same native library

 var data = new FormData();
    data.append("file", {
                          name: 'image.png',
                          type: 'image/png,
                          uri: 'file:///file-cache-url'
                        }, "image.png");
     
    var xhr = new XMLHttpRequest();
    xhr.withCredentials = true;
    
    xhr.addEventListener("readystatechange", function() {
      if(this.readyState === 4) {
        console.log(this.responseText);
      }
    });

xhr.open("POST", "http://127.0.0.1:3000/data/upload");

xhr.send(data);
§普罗旺斯的薰衣草 2025-01-18 01:38:19

以 BLOB 形式获取图像

 const blob = await new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.onload = function () {
      resolve(xhr.response);
    };
    xhr.onerror = function (e) {
      reject(new TypeError("Network request failed"));
    };
    xhr.responseType = "blob";
    xhr.open("GET", "FILE_URI_HERE", true);
    xhr.send(null);
  });

Fetch image as BLOB

 const blob = await new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.onload = function () {
      resolve(xhr.response);
    };
    xhr.onerror = function (e) {
      reject(new TypeError("Network request failed"));
    };
    xhr.responseType = "blob";
    xhr.open("GET", "FILE_URI_HERE", true);
    xhr.send(null);
  });

一杯敬自由 2025-01-18 01:38:19

解决此问题的此处使用的transformRequest方法对我不起作用,因此我采用了使用JSON.stringify的解决方法。

const formData = new FormData()
...

MyApiInstance.post('endpoint', JSON.stringify(formData)).then(() ...

希望这对某人有帮助。

The transformRequest method used here of solving this issue is not working on me so I did a workaround of using JSON.stringify.

const formData = new FormData()
...

MyApiInstance.post('endpoint', JSON.stringify(formData)).then(() ...

hope this help someone.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文