Axios: Axios 不在本机中发送表单数据

创建于 2018-01-25  ·  46评论  ·  资料来源: axios/axios

我尝试使用 axios 发送表单数据,但我不能,在 chrome 开发工具中,请求中没有出现任何内容。 通常通过邮递员发出相同的请求 API 响应。
js (newData) => { const data = new FormData(); data.append('name', 'raphael'); data.append('file', { uri: newData.image.path, type: 'image/jpeg', name: 'teste' }); return axios.post(`${constants.development.URL_API}/file`, data, headers: { 'Content-Type': 'multipart/form-data', }, })`

最有用的评论

最新的 axios 仍然会发生此错误,为什么将其关闭?

所有46条评论

@corujoraphael出于好奇,这个请求是否更早

@corujoraphael我不确定您的代码是否按原样运行。 您指定标题的配置应该是一个对象,但它缺少一个大括号:

(newData) => {
  const data = new FormData();
  data.append('name', 'raphael');
  data.append('file', {
    uri: newData.image.path,
    type: 'image/jpeg',
    name: 'teste'
  });

  return axios.post(
    `${constants.development.URL_API}/file`,
    data, 
    { 
      headers: {
        'Content-Type': 'multipart/form-data',
      }
    },
  )
}

由于此问题尚未收到回复,而且根据我们掌握的信息,这看起来不像是 Axios 错误,因此我将关闭此问题。

如果您在调试代码时需要进一步帮助,请在Stack OverflowGitter上发帖,或再次对此问题发表评论。

谢谢!

@emilyemorehouse ,我使用 React Native FormData 遇到了同样的问题

let s = JSON.stringify({ uri: localUri, name: filename, type: type });
let formData = new FormData();
formData.append('ph0t0', s);

axios.post("http://10.0.1.2:8888/uploadphoto", {
        method: "POST",
        headers: {
                'Content-Type': 'multipart/form-data; charset=utf-8; boundary="another cool boundary";'
        },
        body: formData,
}).then((resp) => {
        console.log(resp);
}).catch(err => {
        console.log(err);
});

期望 MultipartForm、Form 或 PostForm 中存在一些键值

2018/02/20 18:25:31.740 [W] [photo.go:411] req.MultipartForm: nil
2018/02/20 18:25:31.740 [W] [photo.go:412] req.Form: map[]
2018/02/20 18:25:31.740 [W] [photo.go:413] 要求
2018/02/20 18:25:31.740 [W] [photo.go:410] 要求:&{POST /uploadphoto/dialog/57120e8951c643ab42a8c19f/00000000000000000000000000000000000000000000000000000000000000000000001 =utf-8] User-Agent:[okhttp/3.6.0] Accept:[application/json, text/plain, / ] Content-Length:[419] Connection:[Keep-Alive] Accept-Encoding:[gzip] Cookie:[lang=zh-TW; PVsessionID=db9a21d63b2d0ea47b68fa8755bd87e2]] 0xc420e3cb80419 [] 假 10.0.1.2:8888 地图 [] 地图 []地图[] 10.0.1.3:46904 /uploadphoto/dialog/57120e8951c643ab42a8c19f/0000000000000000000000010xc420e3cb40}
2018/02/20 18:25:31.740 [E] [photo.go:425] [UploadPhotos] 错误:请求内容类型不是多部分/表单数据

版本信息
轴心:0.16.2
世博会:25.0.0
反应:16.2.0
反应原生:0.52.0

最新的 axios 仍然会发生此错误,为什么将其关闭?

如果有人可以提供可重复的示例,我很乐意打开它。

@Ernie6711看起来您的代码中有错误——我认为您不应该在将文件数据附加到表单数据之前对其进行字符串化。 此外,axios.post 的参数是axios.post(url[, data[, config]])

这是基于您的代码的示例:

const file ={ uri: localUri, name: filename, type: type};
const formData = new FormData();
formData.append('file', s);

const config = {
        headers: {
                'Content-Type': 'multipart/form-data; charset=utf-8; boundary="another cool boundary";'
        }
};

axios.post("http://10.0.1.2:8888/uploadphoto", formData, config).then((resp) => {
        console.log(resp);
}).catch(err => {
        console.log(err);
});

@emilyemorehouse请检查wireshark 痕迹。 数据已上传,但未使用正确的表单数据编码。 上面的例子可以重现这个问题。 再次 - 请求已成功发送,但是否编码错误。

POST /myserver HTTP/1.1
Content-Type: multipart/form-data

_parts=USERX%2Cusername&_parts=FILE1%2C%5Bobject%20Object%5D

我有一个用于文件上传的本地客户端和服务器示例,尽管在 React Native 环境之外,但它可以工作并且正确编码。 上面的示例实际上无法重现,因为它依赖于我无权访问的变量和服务器。

我的猜测是,如果上传有问题,那是因为附加到表单数据对象的数据无效。

@emilyemorehouse文件上传在浏览器环境中完美运行,它们只会在本机反应时失败。 正如你自己提到的 - 你的测试不在本机环境中,我会从那里开始:)

在 react native 中尝试一个简单的文件上传,只需检查 wireshark 跟踪,你甚至不需要一个工作服务器......

我也一样,Axios 没有反应原生

@duongtranpyco我已经从我的项目中删除了 axios,而是编写了自己的简单类,尽情享受吧!

PS如果你主要是发送JSON,请修改代码。 就我而言,服务器通常需要一个表单。

const request = async ({url, method = 'GET', params, body, responseType = 'json', headers = {}})=>{
    const escape = (data, encode = encodeURIComponent)=>Object.keys(data||{}).reduce((pairs, key)=>{
        for (let value of [].concat(data[key]))
            pairs.push([`${key}`, `${value}`]);
        return pairs;
    }, []).map(pair=>pair.map(encode).join('=')).join('&');

    if (Object.keys(params||{}).length)
        url += '?'+escape(params);
    if (method=='POST' && typeof body=='object')
    {
        if (body instanceof FormData)
            headers['Content-Type'] = 'multipart/form-data';
        else
        {
            body = escape(body);
            headers['Content-Type'] = 'application/x-www-form-urlencoded';
        }
    }
    let {statusCode, request: req} = await new Promise((resolve, reject)=>{
        let xhr = new XMLHttpRequest();
        xhr.open(method, url, true);
        xhr.withCredentials = true;
        xhr.responseType = {json: 'text'}[responseType]||responseType;
        xhr.onload = ()=>resolve({statusCode: xhr.status, request: xhr});
        xhr.onerror = ()=>reject(new TypeError('Network request failed'));
        xhr.ontimeout = ()=>reject(new TypeError('Network request timed out'));
        for (let key in headers)
            xhr.setRequestHeader(key, headers[key]);
        xhr.send(body||null);
    });
    if (statusCode<200 || statusCode>=400)
        throw new Error(`network request failed with ${statusCode}: ${url}`);
    switch(responseType)
    {
        case 'json':
            return JSON.parse(req.responseText);
        case 'text':
            return req.responseText;
        case 'request':
            return req;
    }
    return req.response;
};

request.get = (url, opt = {})=>request({...opt, url, body: null});
request.post = (url, ...args)=>request({...args[1]||{}, url, method: 'POST', body: args[0]});

你好,我面临同样的问题。 有没有人找到解决办法?

第二个@giladno。 由于我正在处理其他部分,因此我使用了一种解决方法:在上传图像时使用 fetch() 编写特定函数。

之前尝试过,对数据或参数进行字符串化都不会影响结果。 服务器收到呼叫但没有发送数据。

@Ernie6711显然标题已损坏,这就是服务器无法接受表单数据的原因。 我用 fetch() 实现了解决方法,它没有问题。

我确实在 react-native 中遇到了一些问题。
问题不在于标题。
在网络中,我们可以有例如:

let formData = new FormData()
formData.append('key', true // bool value)

但在 react native 中,key 的值必须是字符串。

formData.append('key', 'true')

当我发布到一个 url 时,我在 react native 上遇到了同样的问题,正如@giladno提到的,你应该在 react native 中进行测试,你可以验证人们报告的错误 @emilyemorehouse。 我在 14 天前报告了一个错误https://github.com/axios/axios/issues/1618 ,但没有人回应,请在你的库的自述文件中描述你在 react native 上不支持 axios,以便许多开发人员不会浪费时间..!

你们大家,我很欣赏这个方向,但“仅在 React Native 中测试文件上传”并不那么容易。 我不经常在 React Native 中工作,并且需要相当长的时间来启动一个带有文件上传的项目以进行测试。

我确实有一个简单的 POST,其中包含在 React Native 中工作的表单数据:

    const formData = new FormData();
    formData.append("data", true);

    const config = {
      headers: {
        "Content-Type": "multipart/form-data; charset=utf-8;"
      }
    };

    axios.post(URL, formData, config).then(
      response => {
        console.log({ response });
      },
      error => {
        console.log({ error });
      }
    );

true在发送到服务器时会被字符串化,这很有趣。

也就是说,如果有人可以提供一个我可以轻松启动的示例,我很乐意对其进行更多研究。

@corujoraphael你是如何解决这个问题的?

我在追加之前在图像对象中添加了一个类型,如"Image.type='image/png" ,并将内容类型更改为"Content-Type":"multipart/form-data"

        image.type='image/png'
        formData.append("resource", image);
        return axios
          .post('yourBAckendUrl', formData, {
            headers: {
              Authorization: "yourTokenHere",
              "Content-Type": "multipart/form-data"
            }
          })

希望这有助于某人。

我也无法使其正常工作,我正在尝试将多部分/表单数据放入 S3(视频)。 使用 type 选项没有帮助。 multipart/form-data 标头似乎不在 PUT 请求中:

      const data = new FormData();
      data.append('video', {
          uri: 'file:///<path_to_video_on_iphone.mov',
          type: 'video/quicktime',
          name: 'video.mov',
      });
      response = yield call(() => {
        return api.put(url, data, {
          headers: {
              'Content-Type': 'multipart/form-data',
          },
          transformRequest: [
            (data, headers) => {
                delete headers.common.Authorization;
                return data;
            }
          ]
        });
      });

对于这种情况,请使用 fetch :D

var data = new FormData();  
data.append('my_photo', {  
  uri: filePath, // your file path string
  name: 'my_photo.jpg',
  type: 'image/jpg'
}

fetch(path, {  
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'multipart/form-data'
  },
  method: 'POST',
  body: data
});

在 axios 版本中0.18.0有同样的问题。
axios 在创建FormData时,如果post, put等由于某种原因没有正文,则在内部删除标头Content-Type正文保持为空。
这是我的代码:

const sendFormData = images => {
   // images is an array of base64 images (strings)
    const formData = new FormData();
    images.forEach((img, i) => {
        formData.append('file', img);
        formData.append('name', `${type}-${i + 1}`);
    });

    config.headers = {
        .'Content-Type': 'multipart/form-data'
     };

     return axios.post(`http://someurl.com/api/upload-images`, formData, config)
            .then(response => {
               // handle success
            })
            .catch(err => {
                // handle err
     });
}

React Native 版本0.55.3
此示例代码不起作用。 请求正文为空,并删除了Content-Type标头

我有同样的问题,当我检查调试时我的身体是字符串

screen shot 2018-10-26 at 11 12 10 am

这里是我的代码

        const formData = new FormData();
        formData.append('photo', {
          uri: response.uri.replace('file://', ''),
          mineType: 'image/jpeg',
          fileType: 'image/jpg',
          type: 'image/jpg',
          name: 'test.jpg'
        });

        console.log('form data', formData);

         Axios({
           method: 'post',
           url: 'https://dev-host.luxstay.net/api/rooms/10740/photos',
           data: formData,
           headers: {
             Authorization: token,
             'Content-Type': 'multipart/form-data'
           }
         });

更新:发生错误,因为应用程序处于调试模式。 当我关闭调试模式时,它起作用了

axios 在其 xhr 适配器中有一个代码
if (utils.isFormData(requestData)) { delete requestHeaders['Content-Type']; // Let the browser set it }
我猜在 react-native 中,如果您发送多部分表单数据,即使您在代码中设置它,它也会删除内容类型标头。
但我不确定评论该行是否会在 react-native 中解决您的问题。

在 axios 版本中0.18.0有同样的问题。
axios 在创建FormData时,如果post, put等由于某种原因没有正文,则在内部删除标头Content-Type正文保持为空。
这是我的代码:

const sendFormData = images => {
   // images is an array of base64 images (strings)
    const formData = new FormData();
    images.forEach((img, i) => {
        formData.append('file', img);
        formData.append('name', `${type}-${i + 1}`);
    });

    config.headers = {
        .'Content-Type': 'multipart/form-data'
     };

     return axios.post(`http://someurl.com/api/upload-images`, formData, config)
            .then(response => {
               // handle success
            })
            .catch(err => {
                // handle err
     });
}

React Native 版本0.55.3
此示例代码不起作用。 请求正文为空,并删除了Content-Type标头

screen shot 2018-10-26 at 11 12 10 am

那么它应该是什么样子的呢? 我也有对象对象。

@tkserver看起来像当你有一个对象然后你 toString() 它。

const a = {
  name: 'dasdasd'
}
console.log(a.toString());

@tkserver看起来像当你有一个对象然后你 toString() 它。

const a = {
  name: 'dasdasd'
}
console.log(a.toString());

可能我没说清楚。 查看标题时,请求有效负载是否应该显示 [object Object]?

@tkserver如果您的调试器启用了网络检查,它将覆盖 react-native 的 FormData 并导致传递空的 FormData 对象,该对象在网络检查中看起来像 [Object object]。
尝试通过关闭网络检查发出请求,希望这会有所帮助。

感谢 Aman725、minhphung210 等。 当我在真实设备上使用代码时,上传工作正常。 这似乎与iOS模拟器有关。

我遇到了这个问题,但现在已经解决了。

原因是我正在调试网络请求。 我在我的应用程序的入口点中有这行代码:

GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest;

我评论了它,它现在有效。

// IMPORTANT: this will cause FormData requests to fail.
// GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest;

我刚刚发现这个: https :

XMLHttpRequest

你能告诉我你是如何构建请求以使其作为多方正确上传的吗? 我不断收到网络错误:

Error: Network Error
    at createError (blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:168963:17)
    at XMLHttpRequest.handleError (blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:168871:16)
    at XMLHttpRequest.dispatchEvent (blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:28708:27)
    at XMLHttpRequest.setReadyState (blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:28461:20)
    at XMLHttpRequest.__didCompleteResponse (blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:28288:16)
    at blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:28398:47
    at RCTDeviceEventEmitter.emit (blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:3291:37)
    at MessageQueue.__callFunction (blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:2588:44)
    at blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:2345:17
    at MessageQueue.__guard (blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:2542:13)

更新:现在设法让它工作。 目前使用:

formData.append('picture', {
          uri: data.uri,
          name: fname,
          type: 'image/' + ext

        });

如果人们仍然遇到此问题,并且您有
GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest;
调试网络请求的片段,尝试添加
GLOBAL.FormData = GLOBAL.originalFormData || GLOBAL.FormData
它对我有用。

我在追加之前在图像对象中添加了一个类型,如"Image.type='image/png" ,并将内容类型更改为"Content-Type":"multipart/form-data"

        image.type='image/png'
        formData.append("resource", image);
        return axios
          .post('yourBAckendUrl', formData, {
            headers: {
              Authorization: "yourTokenHere",
              "Content-Type": "multipart/form-data"
            }
          })

希望这有助于某人。

谢谢你的帮助! 我可以使用 iOS Simunator 上传我的图片,但无法使用 android 模拟器上传我的图片。

在我将图像类型设置为“图像/jpeg”后,我不再出现网络错误。

const formData = new FormData();
formData.append('file', {
  uri: pictureUri,
  type: 'image/jpeg',
  name: 'profile-picture'
})

我在追加之前在图像对象中添加了一个类型,如"Image.type='image/png" ,并将内容类型更改为"Content-Type":"multipart/form-data"

        image.type='image/png'
        formData.append("resource", image);
        return axios
          .post('yourBAckendUrl', formData, {
            headers: {
              Authorization: "yourTokenHere",
              "Content-Type": "multipart/form-data"
            }
          })

希望这有助于某人。

谢谢你的帮助! 我可以使用 iOS Simunator 上传我的图片,但无法使用 android 模拟器上传我的图片。

在我将图像类型设置为“图像/jpeg”后,我不再出现网络错误。

const formData = new FormData();
formData.append('file', {
  uri: pictureUri,
  type: 'image/jpeg',
  name: 'profile-picture'
})

对于这可能有帮助的任何人,如果您不知道将发送的内容类型,请使用multipart/form-data 。 现在读这个听起来很明显,但我花了一个小时才让任何媒体工作。

    data.append("image", {
      name: "some_name", // also, won't work without this. A name is required
      height: image.height,
      width: image.width,
      type: "multipart/form-data", // <-- this part here
      uri:
        Platform.OS === "android" ? image.uri : image.uri.replace("file:/", "")
    });

嗨,我正在尝试在 Vue.Js 中文件 Axios 上传。 任何人都可以审查并解释这个问题吗?

在 HTML 中
<input type="file" id="file" ref="file" multiple @change="assignFiles"/>

在 Js

`assignFiles(e){

      let uploadedFiles = this.$refs.file.files;
      for( var i = 0; i < uploadedFiles.length; i++ ) { 
        this.form.AttachmentDocs.push(uploadedFiles[i]);           
      }
      console.log(this.form.AttachmentDocs);
 },`

因此,在触发帖子的同时,我正在附加表单数据。

`继续保存(e){

      e.preventDefault();
      this.$v.$touch();
      if(this.$v.$invalid) {
        return;
      }
    this.showLoading(this.loaderId,true);
      this.postDatas.append('form',JSON.stringify(this.form));
      for( var i = 0; i < this.form.AttachmentDocs.length; i++ ){ 
        let attachment = this.form.AttachmentDocs[i];
        this.postDatas.append('files['+i+']',attachment,attachment.name);           
      }

}`

所以在帖子中,我检查了控制台窗口标题,那里显示

文件[0]:(二进制)
文件[1]:(二进制)
文件[2]:(二进制)
文件[3]:(二进制)

在我的服务器端,我无法获取文件。

可能有关系

this.postDatas.append('files['+i+']',attachment,attachment.name);  

试试files['+' + i + '+']

我对 fetch api 有同样的问题。 节点 js 中的 req.body 为空。 使用“express-foridable”解决了这个问题。 https://www.npmjs.com/package/express-formidable

可能有关系

this.postDatas.append('files['+i+']',attachment,attachment.name);  

试试files['+' + i + '+']

Sry + 表示串联,wat 是使用字符串 '+' 。 结果将是文件[+0+]

我对 fetch api 有同样的问题。 节点 js 中的 req.body 为空。 使用“express-foridable”解决了这个问题。 https://www.npmjs.com/package/express-formidable

你包括app.use(express.json({ extended: false }));吗?

可能有关系

this.postDatas.append('files['+i+']',attachment,attachment.name);  

试试files['+' + i + '+']

Sry + 表示串联,wat 是使用字符串 '+' 。 结果将是文件[+0+]

您当前的代码将始终在您的 for 循环中生成files[+i+] 。 它永远不会是files[+0+], files[+1+], files[+2+], etc

此外, files[+0+]永远不会存在。 不确定你要做什么。 你需要files[0], files[1], files[2]...吗? 如果您正在尝试构建一个对象,那么您可以拥有files['+0+'] ,但是,同样,我不确定您要完成什么。

我对 fetch api 有同样的问题。 节点 js 中的 req.body 为空。 使用“express-foridable”解决了这个问题。 https://www.npmjs.com/package/express-formidable

你包括app.use(express.json({ extended: false }));吗?
不。但是,在强大的我有一个问题。 上传的图片将请求字段。 请求文件中没有任何内容。 不知道为什么会这样。

@duongtranpyco我已经从我的项目中删除了 axios,而是编写了自己的简单类,尽情享受吧!

PS如果你主要是发送JSON,请修改代码。 就我而言,服务器通常需要一个表单。

const request = async ({url, method = 'GET', params, body, responseType = 'json', headers = {}})=>{
    const escape = (data, encode = encodeURIComponent)=>Object.keys(data||{}).reduce((pairs, key)=>{
        for (let value of [].concat(data[key]))
            pairs.push([`${key}`, `${value}`]);
        return pairs;
    }, []).map(pair=>pair.map(encode).join('=')).join('&');

    if (Object.keys(params||{}).length)
        url += '?'+escape(params);
    if (method=='POST' && typeof body=='object')
    {
        if (body instanceof FormData)
            headers['Content-Type'] = 'multipart/form-data';
        else
        {
            body = escape(body);
            headers['Content-Type'] = 'application/x-www-form-urlencoded';
        }
    }
    let {statusCode, request: req} = await new Promise((resolve, reject)=>{
        let xhr = new XMLHttpRequest();
        xhr.open(method, url, true);
        xhr.withCredentials = true;
        xhr.responseType = {json: 'text'}[responseType]||responseType;
        xhr.onload = ()=>resolve({statusCode: xhr.status, request: xhr});
        xhr.onerror = ()=>reject(new TypeError('Network request failed'));
        xhr.ontimeout = ()=>reject(new TypeError('Network request timed out'));
        for (let key in headers)
            xhr.setRequestHeader(key, headers[key]);
        xhr.send(body||null);
    });
    if (statusCode<200 || statusCode>=400)
        throw new Error(`network request failed with ${statusCode}: ${url}`);
    switch(responseType)
    {
        case 'json':
            return JSON.parse(req.responseText);
        case 'text':
            return req.responseText;
        case 'request':
            return req;
    }
    return req.response;
};

request.get = (url, opt = {})=>request({...opt, url, body: null});
request.post = (url, ...args)=>request({...args[1]||{}, url, method: 'POST', body: args[0]});

我在我的项目中使用此代码。 我试图理解这段代码。 一个问题,这条线是否必要,
for (let value of [].concat(data[key]))? 可以简单的写成,
pair.push([ ${key} , ${data[key]} ]);

如果人们仍然遇到此问题,并且您有
GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest;
调试网络请求的片段,尝试添加
GLOBAL.FormData = GLOBAL.originalFormData || GLOBAL.FormData
它对我有用。

在哪儿?

我也遇到了这个问题。 这是由android中的文件路径引起的。
const 路径 = utils.isAndroid() ?
它可以正常执行以下操作

    const formData = new FormData();
    const path = utils.isAndroid() ? `file://${filePath}` : filePath;
    formData.append('Voice', {
      uri: path,
      name: 'test',
      type: 'audio/wav',
    });

    formData.append('Content-Type', 'audio/wav');
     const headers =  {
        'Content-Type': 'multipart/form-data',
      };
    return this._sendRequest(url, 'POST', formData, headers);
 data.append('file', {
    uri: newData.image.path,
    type: 'image/jpeg',
    name: 'teste'

使用名称如: name:'teste.jpeg'它将起作用。 您需要为文件提供格式,否则它将无法正常工作。
我通过名称来修复它:'example.jpeg'

在尝试使用 axios 上传视频几天后,我放弃了。 RNFetchBlob 是从 Android 上传文件的更好选择。 这部分很容易实现

rn-fetch-blob

此页面是否有帮助?
0 / 5 - 0 等级