Axios: 无法使用 'Content-Type': 'multipart/form-data' 的 .post 工作

创建于 2016-05-11  ·  99评论  ·  资料来源: axios/axios

我今天花了几个小时试图获得一个发布请求,以使用一些参数和一个我需要上传的文件。

我能够使其与纯 javascript 和 XMLHttpRequest 一起使用,但它不适用于 Axios。 我究竟做错了什么?

下面是使用 XMLHttpRequest 工作的代码:

let data = new FormData();

data.append('action', 'ADD');
data.append('param', 0);
data.append('secondParam', 0);
data.append('file', new Blob([payload], { type: 'text/csv' }));

// this works
let request = new XMLHttpRequest();
request.open('POST', url);
request.send(data);

那会是什么“Axios”版本?

这是我的尝试之一(简单的):

// this won't work
const config = { headers: { 'Content-Type': 'multipart/form-data' } };
    axios.post(url, data, config)
    .then(response => console.log(response))
    .catch(errors => console.log(errors));

谢谢! 感谢您与 Axios 的出色合作!

最有用的评论

@rafaelbiten我刚刚尝试重现该问题,但无济于事。 我使用了以下代码:

const data = new FormData();

data.append('action', 'ADD');
data.append('param', 0);
data.append('secondParam', 0);
data.append('file', new Blob(['test payload'], { type: 'text/csv' }));

axios.post('http://httpbin.org/post', data);

数据成功发送到服务器:

screen shot 2016-05-12 at 9 12 19 pm

所有99条评论

代码对我来说看起来不错。 (你不需要设置 Content-Type,但这并不重要。)当你尝试通过 axios 发送请求时会发生什么?

我注意到设置 Content-Type 与否不会改变这种情况下的任何内容。 当我尝试使用 Axios 发送请求时,数据似乎是一个空字符串,因此后端将响应与缺少参数相关的错误。

我使用的是 0.9.1,但问题在 0.11.0 上仍然存在。

如果还有什么我可以做的来帮助调试这个,请告诉我,好吗?
谢谢@nickuraltsev

您能否在 Chrome 开发工具网络面板中查看您的请求的外观,并在可能的情况下提供屏幕截图?

@nickuraltsev看看这是否有帮助:

screen shot 2016-05-11 at 2 56 12 pm

我认为请求标头是错误的。

所以没有请求有效载荷?

好吧,我们应该有,但数据是一个空字符串。 我不知道是什么破坏了它(考虑到我在第一篇文章中分享的代码)。

我知道了。 并且在开发工具中没有针对您的请求的请求有效负载部分,对吗?

可能相关的标题问题。 当内容类型在请求的配置对象中设置时,它被连接起来,例如
axios.post(
'https://example.com/login',
{emailAddress:电子邮件,密码:hashedPassword},
{标头:{'内容类型':'应用程序/json'}}
);

标头内容类型为 application/json,application/json
在这种情况下不会解析正文

@nickuraltsev对! 您在该屏幕截图上看到的就是我在开发工具上的全部内容。
@rrapant可能是对的,但我几乎可以肯定设置'Content-Type'或不设置,至少在这种情况下,并没有改变任何东西。 我必须再次检查才能确定。

@rrapant重复内容类型值的问题已由#317 修复。 该修复将包含在下一个版本中。 谢谢!

@rafaelbiten我刚刚尝试重现该问题,但无济于事。 我使用了以下代码:

const data = new FormData();

data.append('action', 'ADD');
data.append('param', 0);
data.append('secondParam', 0);
data.append('file', new Blob(['test payload'], { type: 'text/csv' }));

axios.post('http://httpbin.org/post', data);

数据成功发送到服务器:

screen shot 2016-05-12 at 9 12 19 pm

@rafaelbiten您能否尝试使用 FromData 向http://httpbin.org/post发送请求,就像我的代码片段中一样?

暂时关闭这个。 如有必要,请随时重新打开。

@nickuraltsev ,我遇到了同样的问题。

      var fd = new FormData();
      fd.append('file', this.refs.multipartfiles.files[0]);

            const config = { headers: { 'Content-Type': 'multipart/form-data' } };
            axios.post('/dataAPI/sendFile', {
                "UploadCommand": fd
              }, config)
              .then(function (response) {
                console.log(response);
              })
              .catch(function (error) {
                console.log(error);
              });

请在下面找到我的标题信息的屏幕截图,

image

我有一个问题,_axios是否支持向节点服务器发送多部分数据文件?_

@Sreekhar我不知道它是否会起作用,但是您是否可以将 FormData 添加为第二个参数而不是将其包装在另一个对象中?
axios.post('/dataAPI/sendFile', fd, config)

如果你需要使用'UploadCommand'作为文件所在部分的名称,你需要使用这个
fd.append('UploadCommand', this.refs.multipartfiles.files[0]);

@yungpanda我找到了一个替代方案。 我想我现在必须重新创建 API。 无论如何,我会尝试检查它是否有效,我会保持线程更新。 感谢您的回复。

@Sreekhar将 Content-Type 设置为 undefined 以让浏览器将其更改为 multipart/form-data 并自动添加边界

@nickuraltsev这是一个在节点上不起作用的最小示例:

const data = new FormData();

data.append('action', 'ADD');
data.append('param', 0);
data.append('secondParam', 0);

axios.post('http://httpbin.org/post', data).then(req => {
  console.log('Req done: ', req)
}).catch(err => {
  console.error('Error: ', err)
})

错误:结束后写入

@krzkaczor您是否找到了使用 axios 发送 multipart/form-data 的任何解决方法?

@PierreCavalet不,我用request-promise代替。

@krzkaczor谢谢,也被迫切换

@krzkaczor如果您还没有这样做,请尝试添加内容类型

const config = { headers: { 'Content-Type': 'multipart/form-data' } };
let fd = new FormData();
fd.append('file',files[0])
return axios.post("http://localhost:5000/upload", fd, config)

@krzkaczor我也面临与 axios 和 multipart/form-data 相同的问题。 您能否发布您在 request-promise 中使用的代码的要点。

@dan-boa 你去: https ://gist.github.com/krzkaczor/bdbe09d4096b051a3c18387c4ca79a06 它还展示了如何将字符串作为文件发送(设置路径)

如果有人想知道,这里有一个如何将FormDataaxios一起使用的示例。 您基本上必须将数据流式传输到缓冲区并传递正确的标头。

const concat = require("concat-stream")
const fd = new FormData()

fd.append("hello", "world")
fd.append("file", fs.createReadStream(file))
fd.pipe(concat(data => {
  axios.post("/hello", data, {
    headers: fd.getHeaders()
  })
}))

我有同样的问题(在浏览器中,而不是在节点中)。 事实证明,如果您根本不设置Content-Type标头并让 axios 解决问题,它会起作用(还要检查您是否也没有将该标头设置为 axios 拦截器中的默认值。如果您需要一些其余 API 调用的默认值,您可以为 FormData() 请求创建一个单独的 axios 实例)

当我尝试上传到另一个远程服务器时,我最终在节点端使用了 request-promise。

出于同样的原因,我切换到了 request-promise。 否则爱 axios!

@guncha您的示例在 0.15.3 中为我工作,直到我尝试上传一个二进制文件,该文件最终被编码为 UTF8。 告诉 concat 使用缓冲区解决了这个问题。

const concat = require("concat-stream")
const fd = new FormData()

fd.append("hello", "world")
fd.append("file", fs.createReadStream(binaryFile))
fd.pipe(concat({encoding: 'buffer'}, data => {
  axios.post("/hello", data, {
    headers: fd.getHeaders()
  })
}))

或者,我会使用一个承诺:

const promise = new Promise((resolve) => {
  const fd = new FormData();
  fd.append("hello", "world");
  fd.append("file", fs.createReadStream(binaryFile));
  fd.pipe(concat({ encoding: 'buffer' }, data => resolve({ data, headers: fd.getHeaders() })));
});
promise.then(({ data, headers }) => axios.post('/hello', data, { headers }));
const callApi = (url, params) => {
  const formData  = new FormData()
  for(let name in params) {
    let param = params[name]
    if (typeof param === 'object') {
      param = JSON.stringify(params[name])
    }
    formData.append(name, param)
  }

  return axios.post(url, formData)
    .then(response => {
      console.log(response)
    })
}

@guncha为我工作。 谢谢

同样的问题在这里

只需将边界添加到Content-Type

const request = require('axios');
const FormData = require('form-data');
const fs = require('fs');

let data = new FormData();
data.append('file1', fs.createReadStream('./image1.jpeg'), 'image1.jpeg');
data.append('file2', fs.createReadStream('./image2.jpeg'), 'image2.jpeg');

let options = {
    method: 'POST',
    url: 'http://localhost:3200/upload',
    headers: {
        'Content-Type': `multipart/form-data; boundary=${data._boundary}`
    },
    data
};

return request(options)
    .then(response => {
        console.log(response);
    });

嘿,
我得到了这个 json 格式的文件,谁能帮我把它转换成多部分文件。
使用的平台是java8。
"body": "------WebKitFormBoundaryQsJGeBuR8e9dQ4Pm\r\nContent-Disposition: form-data; name=\"file\"; filename=\"backup prolog.txt\"\r\nContent-Type: text/plain\r\n\r\n%All the Pre-Defined relations\r\nconnected(hira,rohit,father).\r\nconnected(rohit,rakesh,father).\r\nconnected(ram,hira,father).\r\nconnected(kavri,hira,mother).\r\nconnected(hira,kavri,son).\r\nconnected(arun,vinayak,father).\r\nconnected(vinayak,arun,son).\r\nconnected(arun,shashi,husband).\r\nconnected(shashi,arun,wife).\r\nconnected(vinayak,vardaan,brother).\r\nconnected(vardaan,vinayak,brother).\r\nconnected(shashi,vinayak,mother).\r\nconnected(vinayak,shashi,son).\r\n\r\n\r\n\r\nconnected2(X,Y,D) :- connected(X,Y,D).\r\n%connected2(X,Y,D) :- connected(Y,X,D).\r\n\r\nnext_node(Current, Next,R, Path) :-connected2(Current, Next, R),not(member(Next, Path)).\r\n\r\nfunc(how,is,X,related,to,Y):-depth_first(X,Y,[X],P),write(P).\r\n%Procedure to Start the depth_first\r\ndepth_first(Goal, Goal, _, [Goal]).\r\n\r\ndepth_first(Start, Goal, Visited, [Start,is,R,of|Path]) :-next_node(Start, Next_node,R, Visited),depth_first(Next_node, Goal,[Next_node,R|Visited], Path).\r\n\r\n\r\n\r\n\r\n\r\n\r\n------WebKitFormBoundaryQsJGeBuR8e9dQ4Pm--\r\n"
谢谢

代码在浏览器中有效,但在节点上无效。

const fdata = new FormData();
fdata.append('user', u);
fdata.append('hostnames', n.join(' '));
const host = localStorage.getItem('host');
const port = localStorage.getItem('port');
axios({
  url: `http://${host}:${port}/hosts/remove`,
  method: 'post',
  data: fdata
}).then(response => {
  if (response.status === 200) {
    console.log(response.data);
    console.log('Removed host successfully');
  }
  return null;
}).catch(er => console.log(er));

嗨@Sreekhar
对我来说,我将配置更改为
const config = { headers: { 'Content-Type': 'application/json' } };
它工作得很好

请重新打开,直到有一些一致的答案/工作流程。 似乎很多人仍然遇到这个问题。

+1 重新打开

包含二进制文件数据的 HTTP 帖子似乎在 axios v0.16.2 中运行良好

// The following was tested successfully with axios v0.16.2

// Create a new form.  Note:  could also specify an existing form as
// the parameter to the FormData() constructor to copy all the elements
// from the existing form to the new one being created.

var tempFormData = new FormData();

var someNoteValue = 'Hello World';
var someAudioData = [];  // populate this with data from file, with MediaRecorder() etc.


// Add form fields

tempFormData.set('SomeNote', 'Hello World');
tempFormData.set('SomeRecording', someAudioData[0], 'SampleRecording.webm');


// Optional:  output list of form fields to the console for debugging

for (var pair of tempFormData.entries()) {
    console.log('Form field: ' + pair[0] + ', ' + pair[1]);
}


// Call Axios to post the form to myurl

axios({
    method: 'post',
    url: 'myurl',
    data: tempFormData,
    config: { headers: {'Content-Type': 'multipart/form-data' }}
})
    .then(function (response) {
        //handle success
        console.log(response);
    })
    .catch(function (response) {
        //handle error
        console.log(response);
    });

            }

此外,当使用缓冲区表示文件时,这对我有用:

      const form = new FormData();
      const fileBuffer = new Buffer(
        'MM2 - noticeably shallower than the original - score: 101%', 'utf-8'
      );
      form.append('name', 'reviews.txt'); // additional form data field
      form.append('file', fileBuffer, 'original-file-name.bar');

      const res = await axios.post(`/uploadfile`, form, { headers: form.getHeaders() });

需要注意的重要一点:如果您在 Axios 实例的默认值中设置了任何默认数据参数,则上述任何解决方案都不起作用。 您还可以检查您是否在 Axios 实例中指定了默认的 Content-Type 标头(通过 axios.defaults.headers 和 axios.defaults.parameters)。

这可能不是重点,但问题可能与在服务器端使用body-parser有关。 我正在努力解决类似的问题并遇到了这篇文章:

https://philna.sh/blog/2016/06/13/the-surprise-multipart-form-data/

TL;DR - body-parser不处理多部分/表单数据。 换句话说, axios不是问题, body-parser是。 这可能就是上述缓冲溶液起作用的原因。

我认为此功能是出于安全原因,如此处所述:

http://andrewkelley.me/post/do-not-use-bodyparser-with-express-js.html

我希望对某人有所帮助!

我有同样的问题。 我使用 Axios 0.16.2并通过XMLHttpRequest发送有效,但不是通过 Axios。

我有基本的 FormData 对象:

常量 formData = new FormData();
formData.append('name', 'textName');

我尝试了@Janekk的建议:

axios({
      method: 'post',
      url,
      withCredentials: true,
      data: { formData },
    })

然后@faalkhah的建议:

const config = { headers: { 'Content-Type': 'application/json' } };
    axios({
      method: 'post',
      url,
      withCredentials: true,
      data: { formData },
      config,
    })

@askona的建议:

const config = { headers: { 'Content-Type': undefined } };
    axios({
      method: 'post',
      url,
      withCredentials: true,
      data: { formData },
      config,
    })

请求标头为application/jsonformData为空。

我不知道如何尝试@demeter-macik 修复,因为它似乎只适用于后端https://stackoverflow.com/a/13454425/968379

大家好,
我也有同样的问题
我在客户端的代码
`

    const url = '/file/uploadTest';
    const formData = new FormData();
    formData.append('file', file);
    formData.append('params1', value);
    formData.append('params2', value2)

    const config = {
        headers: {
            'Content-Type': 'multipart/form-data',
        }
    }
    axios.post(url,formData,config)`

在 Sails 服务器中,我登录控制台 req.body
我发现,当我调用请求 10 次时,服务器大约有 3 4 次没有收到正文(正文为空)。
我检查了 chrome 的 devtool,请求仍然在有效负载中传输文件和正文。
我还没有弄清楚为什么,但我有一个解决方案

那是请求标头。

`代码

    const url = '/file/uploadTest';
    const formData = new FormData();
    formData.append('file', file);
    formData.append('params1', value);
    formData.append('params2', value2)
    const config = {
        headers: {
            'Content-Type': 'multipart/form-data',
            'params1': value,
            'params2': value2
        }
    }
    axios.post(url,formData,config)`

@Sreekhar
你解决问题了吗? 我没有找到解决方案,请有人帮助我。
另外,提前谢谢你

你好,

我一直在尝试发布 multiformdata(它是一个 Eztext SMS api)
将 axios 与 node.js 一起使用。

它适用于以下代码,
返回新的承诺(功能(解决,拒绝){

        var request = require("request");
        var options = {
            method: 'POST',
            url: 'https://app.eztexting.com/sending/messages',
            qs: {format: 'json'},
            formData:
                {
                    User: '**',
                    Password: '**',
                    'PhoneNumbers[0]': '8572222***',
                    Message: 'Appointment Reminder',
                    MessageTypeID: '1'
                }
        };
        request(options, function (error, response, body) {
            if (error) {
                console.log(error);
                reject(error);
            }
            else {
                console.log(response);
                resolve(response);
            }

            // console.log(body);
        });

但它不适用于 axios,因为没有发送 SMS,但我得到以下请求的状态代码为 200:-
var axios=require('axios');

         axios.post('https://app.eztexting.com/sending/messages', {
             qs: { format: 'json' },
             headers: {
                 'Content-Type': 'application/x-www-form-urlencoded'
             },
             formData:
                 { User: '****',
                     Password: '2sH****5',
                     'PhoneNumbers[0]':'85722******',
                     Message: 'Hello Yahska',
                     MessageTypeID: 1 }
         })
             .then(function (response) {
                 console.log(response);
             })
             .catch(function (error) {
                 console.log(error);
             });

为什么发布请求在“请求”库而不是 Axios 中成功?

您是否尝试过在设置任何标题的情况下将数据从 JSON 转换为 FormData?
应自动处理数据的标头(即除了身份验证标头之外)

async function sendMessage(myJSONPayload){
  try{
    const data = convertJSON2FormData(myJSONPayload);

    const response = await axios.post('https://app.eztexting.com/sending/messages', {
  data
});
    console.log(response);
  } catch(ex){
    console error(err);
  }
}

sendMessage ({ User: '****',
                     Password: '2sH****5',
                     'PhoneNumbers[0]':'85722******',
                     Message: 'Hello Yahska',
                     MessageTypeID: 1 }
         });

对于从 JSON 到 FormData 的转换,请使用类似于此答案的内容

请记住,嵌套键很难处理。 例如,当我们将数据发送到我们的后端时,如果我们像这样将它们展平,它就可以工作:

{a: {b: 2}} --> formData.append("a.b",2)

同样的问题。

当然,@michaelscheurer! 设置请求的标头是不够的:您必须提交 FormData 才能使其工作。 它是一个浏览器对象,它将使用所有适当的边界进行序列化以处理请求......无论是 axios 还是 vanilla js 都不会为您将 JSON 数据转换为 FormData。 Axios 会识别它是一个 FormData 并为你设置标题,所以你不需要设置它们
尝试按照我之前的答案提示...

@Iamuertepeluda
我按照您的建议尝试了以下操作,但没有运气,,,与我获得状态 200 ok 的行为相同,但没有通过以下请求发送 SMS
var axios=require('axios');

    const FormData = require('form-data');

    const form = new FormData();

    //fo this jason I created a form
    // formData:
    // {
    //     User: '*****',
    //         Password
    // :
    //     '******',
    //         'PhoneNumbers[0]'
    // :
    //     '8****2763',
    //         Message
    // :
    //     'Appointment Reminder',
    //         MessageTypeID
    // :
    //     '1'
    // }

    form.append('User','****');
    form.append('Password','*****');
    form.append('PhoneNumbers[0]','*****');
    form.append('Message','Appointment Reminder');
    form.append('MessageTypeID','1');


         axios.post('https://app.eztexting.com/sending/messages', form,
    {
        qs: {format: 'json'},
        headers:
        {
                'content-type'
        :
            'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
        }
    }
)
             .then(function (response) {
                 console.log(response);
             })
             .catch(function (error) {
                 console.log(error);
             });

@Ruchi2729您使用的是 node.js 还是浏览器?

在浏览器中你不需要const FormData = require('form-data');因为 FormData 是本机的。

此外尝试不设置标题和 qs,或尝试

axios.request({
 url: "https://app.eztexting.com/sending/messages"
 type: "post",
 data: form //the instance of FormData of your stub
});

正如我提到的,它应该在浏览器中自动设置标题

@Ruchi2729我看到您正在使用节点,抱歉。
我记得曾经在 axios 上使用过form-data ,但我不记得它是否真的有效。

但是您确定这是使用 eztexting 发送 SMS 的正确方式吗? 从他们的文档来看,它似乎有所不同,就像您应该使用 api 密钥和他们自己的节点客户端......

我们可以重新打开它吗? 看起来很多人仍然反对这一点,包括我自己。 例如,此请求不会通过 axios 按预期发送到服务器,但如果我通过 Postman 发送与multipart/form-data相同的文件,则一切正常。

screen shot 2018-03-26 at 12 22 35 am

编辑:我的问题是尝试将 base64 编码的数据 uri 作为表单数据发送。 如果其他人正在努力解决同样的问题,这里有一些示例代码来转换它:

async function importCsv(data: CsvImportData): Promise<void> {
    const formData = new FormData();
    const headers = {'Content-Type': 'multipart/form-data'};

    formData.append('csv', dataURItoFile(data.file, `upload_${Date.now()}.csv`));

    try {
      await axios.post('https://example.com/api/upload/csv', formData, {headers});
    } catch(e) {
      console.error(e);
    }
}

function dataURItoFile(dataURI: string, defaultFileName: string): File {
  let byteString: string;
  const [metadata, data] = dataURI.split(',');
  if (/base64$/.test(metadata)) {
    byteString = atob(data);
  } else {
    byteString = unescape(data);
  }

  const mimetype: string = metadata.split(':')[1].split(';')[0];
  const filename: string = (metadata.match(/name\=(.*);/) || [])[1] || defaultFileName;

  let dataView: Uint8Array = new Uint8Array(byteString.length);
  for (let i = 0; i < byteString.length; i++) {
    dataView[i] = byteString.charCodeAt(i);
  }
  return new File([dataView], filename);
}

嘿,我指的是这份文件:- https://www.eztexting.com/developers/sms-api-documentation/rest#Sending
您指的是哪个文档以获取 API 密钥和所有内容?

@Ruchi2729
抱歉,我与Nexmo 混淆了,Nexmo 是另一种短信服务,有自己的节点客户端😅

但是无论如何,根据您提到的文档,您可以通过将format设置为json来避免 FormData 并让 axios 发送 JSON 有效负载(您可以让它通过有效负载格式隐式猜测标头)

https://app.eztexting.com/sending/messages?format=json

我想承认这一点的时间更长,所以希望这对某人有所帮助。 我正在使用 axios、express 和 express-fileupload。 我可以使用已附加到 FormData 的参数成功上传到 Node。 我使用 req.files 获取文件,然后使用 req.body['yourfilename'] 获取其余的表单数据

服务器(快递):

screen shot 2018-03-27 at 1 59 08 pm

router.post('/helper/amazon/upload', function(req, res) { if (!req.files) { return res.status(400).send('No files were uploaded.') } console.log(req.body.filename); return console.log(req.files);

前端(axios)

screen shot 2018-03-27 at 1 58 45 pm

const formData = new FormData(); formData.append('file', this.validFile); formData.append('filename', 'trails/' + this.$route.params.id.split('-')[0] + '/camping/'); axios.post( /api/helper/amazon/upload , formData, { headers: { 'Content-Type': 'multipart/form-data' } });

结果:

screen shot 2018-03-27 at 2 02 11 pm

我有同样的问题,我可以看到我用我的开发工具成功发送了文件数据,但是在我的控制器里面我的 $request->file('file') 是空的
我的组件

提交表格() {
this.formData =new FormData();
this.formData.append('file',this.$refs.file.files[0]);
this.formData.append('分析',this.analyticsForm.analysis);
this.formData.append('_method','PATCH');
axios.post('/分析',
this.formData
,{headers: {'Content-Type': 'multipart/form-data'}}).then(response => this.isSubmittedRedirect(false,'/sources/'+this.source+'/description'+'') )
.catch((错误) => console.log(错误))
},

我发现用 FormData 做任何事情都是一个问题,因为 MVC 似乎不喜欢以这种方式获得任何东西,因为您必须将 Content-Type 指定为multipart/form-data并且当我会抛出异常时检查if (!Request.Content.IsMimeMultipartContent()) { throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType); } ,正如微软网站所说的那样: https ://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part-

最好只是将我的文件放入 base64 字符串:
https://stackoverflow.com/questions/37134433/convert-input-file-to-byte-array/49676679#49676679

这篇文章可能与如何做到这一点更相关,因为我在这个例子中使用了 DropZone:
https://stackoverflow.com/questions/32556664/getting-byte-array-through-input-type-file/49660172#49660172

我在这里更详细地介绍了它: https ://stackoverflow.com/questions/47574218/converting-from-blob-to-binary-to-save-it-to-mongodb/49660839#49660839

然后我可以创建一个 JSON 对象:

const myObj = {
   file = myBase64String,
   title = "myfileTitle.jpg"`
   type = "image/jpeg"`
}

我没有使用 axios,而是使用了 XMLHttpRequest。

 const xhr = new XMLHttpRequest();

并打开并设置标题:

 xhr.open('POST', '/api/FileUpload/Post', true);
 xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8' );
 xhr.withCredentials = true;

我设置了onreadystatechange来捕获响应:

xhr.onreadystatechange = (response) =>
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(response.target.responseText);
    }
}

并且寄出:

 xhr.send(JSON.stringify(myObj));

如果你使用 axios,它可能是:

try {
    var axios = require('axios');
    const config = {
        headers: {
            'Content-Type': 'application/json;charset=UTF-8',
        }
    }
    await axios.post('https://example.com/api/upload/post', myObj, config)
        .then(function (response) {
             console.log(response);
         })
         .catch(function (error) {
             console.log(error);
         });
}
catch(e) { console.log(e); }

在 MVC 方面,您需要一个匹配模型:

public class MyModel {
    public string file { get; set; }
    public string title { get; set; }
    public string type { get; set; }
}

然后将其作为带有 [FromBody] 标签的 Post 调用中的参数:

[System.Web.Http.HttpPost]
public virtual JsonResult<string> Post([FromBody]MyModel myModelObject)
{
    string strBase64FileString = myModelObject.file;
    string strTitle = myModelObject.title;
    string strFileType = myModelObject.type;

    return Json(JsonConvert.SerializeObject(new { file = myModelObject.file, title = myModelObject.title, myModelObject.type }));
}

你应该取回你发送的东西。 请注意,如果您将此作为测试实现,请使用非常小的文件执行此操作,这样您就不会永远等待锁定系统的浏览器/内存的可能性。

@navyjax2
我像你说的那样做,它正在处理小文件,但我需要发送大文件(> 250Mo),是的,它锁定了我的浏览器

是的,为此,您可能希望将文件数组分成可管理大小的块并以块的形式发送,在另一端(服务器端)有一个可以重新组合它们的方法,并给它一个参数以便它知道它是哪个块(第一个、第二个、第三个等)以及在它在服务器端处理文件之前期望的总块数。 但我认为,无论你做什么,对于这么大的文件,你都必须等待它完成它的工作。 如果你以块的方式进行内存管理,也必须小心内存管理,因为你必须确保每次都清除或重新使用你的变量,而不是每次都重新实例化相同变量的新版本你做一个块。 少数几个全局变量之一是好的 - 或者每次运行都设置为模型字段。

我同意@epferrari ,请考虑重新打开这个问题。
可以在 chrome 中使用 FormData 发送 base64 字符串,但无法使用 node(v8.9.3) 中的 axios 完成它。
它适用于节点获取......

const fetch = require('node-fetch')
const axios = require('axios')
const FormData = require('form-data')
const base64Img = require('base64-img')

const b64 = base64Img.base64Sync('./test.jpg').split('base64,')[1]
const form = new FormData()
form.append('b64_data', b64)
const headers = form.getHeaders()

// with node-fetch it worked
fetch('http://some.url', {
  method: 'POST',
  body: form,
  headers,
}).then(res => res.text()).then(console.log).catch(console.log)

// not working with axios
axios({
  method: 'POST',
  url: 'http://some.url',
  data: form,
  headers,
}).then(console.log).catch(console.log)

=== 更新 ===
我不明白,我对 node-fetch 和 axios 使用相同的标头,并且似乎它们将相同的表单数据发布到服务器,为什么它们最终会有所不同?
顺便说一句,我发布的真实网址来自这里,我正在做的是用 nodejs 模拟浏览器的 http 请求,将图像发送到服务器并返回链接。

我通过使用解决了这个问题:

<input onChange="emitImageInfo(this)" type="file" multiple>

function emitImageInfo($event){
  let files = $event.target.files
  let formData = new FormData();

  for (let i = 0; i < files.length; i++)
      formData.append('image[' + i + ']', files[i])

  axios.post('file/upload', formData)
     .then((result) => { console.log('got it') })
     .catch((err) => { console.log(err) })
}

这有效:

axios.post(localhost:3000/items, formData, { headers: { 'Content-Type': 'multipart/form-data' }});

我也有同样的问题

不使用 golang

就在Vue里找个简单的方法,不过我觉得可以用在其他情况下。😀
后端:Express.js 和 express-fileupload 包。

<template>
  <div>
    <input type="file"
           name=""
           id="file-upload"
           multiple
           @change="filesChange($event.target.files)">
    <button @click="handleSubmit">Send</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      formData: new FormData(),
    };
  },
  methods: {
    filesChange(fileList) {
      // First: append file to FormData
      Array.from(Array(fileList.length).keys()).map(x => {
        this.formData.append(fileList[x].name, fileList[x]);
      });
    },
    handleSubmit() {
      // Append Text
      this.formData.append('username', 'Jeremy');

      // Append Number: Will be string
      this.formData.append('number', 9527);

      // Append Array: Need to be converted to a string
      this.formData.append('arrData', JSON.stringify([1, 2, 3]));

      // Append Array: Need to be converted to a string
      this.formData.append(
        'objData',
        JSON.stringify({ name: 'Jeremy', age: 28 })
      );

      this.axios({
        method: 'post',
        url: `file/multi-users`,
        data: this.formData,
      }).then(res => {
        console.log(res);
      });
    },
  },
};
</script>

capture

即使我们面临同样的问题。 从 react java 脚本中删除了 content 类型的标头,然后它就可以正常工作了。 早些时候,当您在内容类型中明确设置时,没有设置边界

编辑:在进一步阅读之后,似乎 Express 是我的问题。 希望这对其他人有用

这里同样的问题。 @nickuraltsev强烈建议重新打开该问题。

我正在尝试使用以下代码通过 axios 将文件发布到我的节点服务器:

let ff = new FileReader();
ff.onload = (ev) => {
      var result = ev.target.result;
      console.log(`result: ${result} of type ${typeof(result)}`);
      axios.post('/test', {
                 file: result
                 })
                 .then((response) => {
                         console.log(`Response: ${response}`)
                  })
                  .catch((err) => {
                        console.log(`Test error: ${err}`);
                   })
}

var sampleFile = //getting the file here
ff.readAsArrayBuffer(sampleFile);

请求的正文在服务器端完全是空的

尝试直接发送文件,将文件读取为 ArrayBuffer 并将文件读取为文本(尽管有效负载太大),但所有 3 个都不起作用。

两年后:
同样的问题...

@demeter-macik 谢谢,添加边界对我有用:微笑:

    const form = new FormData();
    form.append('email', '[email protected]');
    form.append('phone_no', '63');
    form.append('phone_code', '9179303100');

    if (logo) {
      form.append('logo', logo);
    }

    const response = await axios({
      method: 'post',
      url: `${apiUrl}users`,
      data: form,
      headers: {
        'content-type': `multipart/form-data; boundary=${form._boundary}`,
      },
    });

这绝对适合我——所有浏览器,包括 Safari iOS。

我的代码是这样的:

功能示例发布(配置){

// save reference this

let that = this;



// can optionally pull in form fields from an existing HTML form)

let myForm = document.getElementById('myForm');

let myFormData = new FormData(myForm);



// add in data from config.data if applicable

if (config && config.data) {

    that.objToStr(config.data, '', myFormData);



    for (let n2 in config.data) {

        if (config.data.hasOwnProperty(n2)) {

            myFormData.set(n2, config.data[n2]);

        }

    }

}



if (config.binaryFiles && config.binaryFiles.length > 0) {



    for (let i = 0; i < config.binaryFiles.length; i = i + 1) {

        let thisFile = config.binaryFiles[i];

        myFormData.append(thisFile.fieldName, thisFile.binaryData, thisFile.fileName)

    }

}





let axiosConfig = {

    method: 'post',

    url: config.url,

    data: myFormData,



    onUploadProgress: config.onUploadProgress,

};



if (config && config.binaryFiles && config.binaryFiles.length > 0) {

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

}

else {

    axiosConfig.headers = {'Content-Type': 'application/x-www-form-urlencoded'};

}



const ax = axios.create();

// note that passing in config to the constructor is broken as of axios v0.19.0-beta.1

// So we work around by passing in config to the request() method



ax.request(axiosConfig)

    .then(function (response) {

        // handle success



        alert(response.data);



    })

};

// 调用 samplePost 上传

样本邮递({

url: 'async',

data: {somefield: 'some value'}, //note: passes in as form fields



// optionally include array of binary files

binaryFiles: thisFileList

});

来自:Antonio Vázquez [email protected]
发送:2018 年 9 月 11 日星期二上午 11:23
至:axios/axios [email protected]
抄送:DavidRueter [email protected] ; 评论[email protected]
主题:回复:[axios/axios] 无法使用 'Content-Type': 'multipart/form-data' 的 .post 工作 (#318)

从 Safari 发出帖子请求需要 4 个小时,而且还在计数。 仍然没有发生......到底是什么家伙?

这里没有一个解决方案对我有用...... :(


您收到此消息是因为您发表了评论。
直接回复此邮件,在 GitHub 上查看https://github.com/axios/axios/issues/318#issuecomment-420371510 ,或将帖子静音https://github.com/notifications/unsubscribe-auth/AFbi6JQBv06LTwL4z3HIAlvXAXDyps1- ks5uZ_9wgaJpZM4Ibm_zhttps://github.com/notifications/beacon/AFbi6BSPfwPvNaWPFSdvtLKRYXS1m4uKks5uZ_9wgaJpZM4Ibm_z.gif

这也对我有用,谢谢@arvi

twiliosms = async (Codigo) => {

var FormData = require('form-data');
var fs = 需要('fs');

var form = new FormData();
form.append('到', '+524772773737');
form.append('发件人', '+737373737');
form.append('Body', Codigo);

尝试 {
让 axapi = 等待 axios(
{
url: '2010-04-01/Accounts/AC8aa53c907943af79234414bb725c2cd3/Messages.json',
baseURL: 'https://api.twilio.com',
标题:{'内容类型': multipart/form-data; boundary=${form._boundary} ,},
数据:表格,
授权:{
用户名:'AC8aa53c907943af79234414bb725c2cd3',
密码: * ,
},
方法:'发布',
}
)

} 捕捉 (e) {console.error(e)}
}

我在徘徊这个库仍然需要表单数据帖子的自写变通方法....

任何更新?

我在 NodeJS 10.11.0 和 Axios 0.18.0 中有类似的错误(参见 #1892)。 我已经尝试过@arvi的修复,但它不起作用。

对我来说,这有效:

let formData = new FormData(document.querySelector('#form'));

axios.post("/api/xxx", formData).then(console.log).catch(console.error)

这行不通

let formData = new FormData(document.querySelector('#form'));

axios.post("/api/xxx", {data: formData}).then(console.log).catch(console.error)

请注意postdata参数格式应该是(url , FormData) ,而不是(url, {data: FormData})

beforeAll(function (done) {

          //parse form fields
          var parsefields = function(req,res){
            var form = new formidable.IncomingForm();
            form.parse(req, function (err, fields, files) {
              if (err) res.status(404).json(err)
              else res.status(200).json(fields);
            });  
          }

          router.route('parsefields').post(parsefields)

          //start server
          s = express()
          s.use('/',router)
          s.listen(4000,(err)=>{done(err)})
          done()
        });

        it('should parse and return form fields', function (done) {

          const fd = new FormData()
          fd.append('key','value')

          axios({
            method: 'POST',
            url: 'http://localhost:4000/parsefields',
            data: fd,
            headers : fd.getHeaders(),
          }).then(function (res) {
            expect(res).to.exist
            expect(res.body.key).to.equals('value')
          }).catch(err => {
            expect(err).not.to.exist
          })
          done()

        });
});

我有同样的问题。 收到没有错误的 404。 将强大的用于表单解析器、express 和 axios。

我不知道这是否对任何人有帮助,但我只在 Safari 上看到了这个问题,并通过使用formdata-polyfill修复了它。 Safari 应该原生支持 FormData.append() 但可能实现略有不同?

编辑:我错了:我使用的是从 Blob 创建的 URL。 一旦我开始使用正确的 blob,一切都像魅力一样!

当我可以上传文件时,我对 Blob 有同样的问题。 从 Blob 转换为 File 很简单,但我想知道这是一个错误还是我误解了语法:

`` js upload () { let data = new FormData() data.append('file', this.croppedFile) data.append('blob', this.croppedBlob, 'blob.jpeg') axios.post('/api/fp/process/', data, { headers: { 'Accept':文本/纯文本`,
},
})

croppedFile is derived from croppedBlob with this simple code:
   `   return new File([this.cropImg], this.file.name, { type: this.file.type })`

Firefox dev tools show:

------WebKitFormBoundarytmInU7WtcHvmgYbc
内容处置:表单数据; 名称=“斑点”

------WebKitFormBoundarytmInU7WtcHvmgYbc
内容处置:表单数据; 名称=“文件”; 文件名="dscn2950.jpg"
内容类型:图片/jpeg

blob:http :// localhost:8080/9a6446d1-1ca2-4fd3-a6c8-8b36d863c146
------WebKitFormBoundarytmInU7WtcHvmgYbc--

```
根据mozilla formData.append 文档,我似乎可以使用 Blob 对象。

让我陷入困境的是我的服务器没有正确处理文件,使用https://www.npmjs.com/package/multer修复了它

它对我有用! 谢谢!

这里没有什么对我有用,因为我的代码非常好。
真正的问题是我从 Windows 搜索结果中拖动的文件 - Chrome 找不到真实位置,它破坏了整个 FormData 解析。 导航到文件并拖动它解决了这个问题。

大家好,
请帮我。

发布https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart HTTP/1.1
授权:不记名 [YOUR_AUTH_TOKEN]
内容类型:多部分/相关; 边界=foo_bar_baz
内容长度:[NUMBER_OF_BYTES_IN_ENTIRE_REQUEST_BODY]

--foo_bar_baz
内容类型:应用程序/json; 字符集=UTF-8

{
“名称”:“我的对象”
}

--foo_bar_baz
内容类型:图片/jpeg

[JPEG_DATA]
--foo_bar_baz--

axios 不支持多部分/相关请求类型

对我来说,这是(我猜)gulp。 因为我在服务器上收到了缩小文件的错误。 我手动删除了 dist 文件夹中的所有内容,将内容类型保留为未定义,并且一切都按预期工作。
所以你会有类似的东西:

formdata.append("selectPaymentType", $scope.extraFields.selectPaymentType);
formdata.append("pickupMethod", $scope.extraFields.selectPickupType);
让请求 = {
方法:'POST',
url: baseURL + '订单',
数据:表单数据,
标题:{
“内容类型”:未定义,
'x-access-token': $scope.userToken
}
};
$http(请求)
.success(函数(d){})
.error(函数 () { });

PS:这是摘录...我还附加了文件和更多字段...

服务器:

var form = new multiparty.Form({uploadDir : './uploads/orders/'});

form.parse(req, function(err, fields, files) {
//你的代码在这里
})

hii plz我需要帮助:我得到“文件:这个值不应该是空白的。” 当我尝试使用 fetch 获取发布图像时:
handleSubmit = (event) => { event.preventDefault(); //const { category } = this.state; console.log(this.state.file) let formData = new FormData(); formData.append("file",this.state.file); formData.append("name",this.state.name); alert('You Added a new Category Named ' + this.state.file); fetch(`${process.env.REACT_APP_BASE_URL}/category/image`, { method: 'POST', body: formData }).then(res => res.json()).then(err => console.log(err)); } 构造函数(道具){
超级(道具);

this.state = {

    name: '',
    file: null
  ,
  isLoaded: false,
  isEditMode: false,

}

}
```

对于任何人来说,这都对我有用。
如果正在使用输入文件,则必须在获得其他输入字段之前,像中间件一样在 router.post('/') 中使用 MULTER。

检查您的 axios.create,此标头应为“标头:{}”并且不使用数据。像这样:
var instance = axios.create({
标题:{
// 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
},
// 数据: {},
参数:{}
});

直到今天,这不适用于 nodejs。 request-promise方法也对我有用。

花了 2 天时间试图让它与 nodejs 中的 axios 一起工作。 花了 30 秒才真正让它在 nodejs 中与 request-promise 一起工作。

我尝试了不同的解决方案,但最后我处理了这个问题,添加了标题:

const FormData = require('form-data')
const axios = require('axios')

const form = new FormData()
form.append('foo', 'bar')

await axios.post('http://myserver', form, { headers: form.getHeaders() })

@Googrosh是的。 是的。 是的。

花了半天时间弄清楚它是否与客户端或服务器配置有关。
最后, headers: form.getHeaders()成功了。

移动到got因为它只是 _works_ 与formDatamultipart/form-data - https://github.com/sindresorhus/got 🙌
关闭,但没有雪茄 Axios 👋

  const form = new FormData()
  const stream = fs.createReadStream(file.path)

  form.append('file', stream, file.name)

  try {
    await got.post('http://example.com', { body: form })
  } catch (error) {
    next(error)
  }

你可以这样做:
handleSubmit = (e: any) => {
e.preventDefault();
常量数据 = 新 FormData();
data.append('product_csv', this.state.csvfile);
让 accessToken = localStorage.getItem('access_token');
axios
.post('/上传', 数据,
{标题:
{ 'Content-Type': 'multipart/form-data', 授权: accessToken }
})
.then(res => {
console.log('res', res);
});
};

@Googrosh Brilliant, .getHeaders()也为我工作。 我无法告诉你我为此花了多少时间。 谢谢!

我正在使用本机反应。 我通过使用rn-fetch-blob结束了这个问题。 太糟糕了 :(

我有同样的问题,它只是不适用于没有任何文件的简单 FormData 并且 .getHeaders() 没有帮助。 移动到“得到”的库,只是工作。 这里也提到了https://github.com/form-data/form-data/issues/458 (我使用的是 Node v12)

2020 ES6 做事方式

拥有 html 中的表单,我在数据中绑定如下:

数据:

form: {
   name: 'Joan Cap de porc',
   email: '[email protected]',
   phone: 2323,
   query: 'cap d\ou'
   file: null,
   legal: false
},

提交:

async submitForm() {
  const formData = new FormData()
  Object.keys(this.form).forEach((key) => {
    formData.append(key, this.form[key])
  })

  try {
    await this.$axios.post('/ajax/contact/contact-us', formData)
    this.$emit('formSent')
  } catch (err) {
    this.errors.push('form_error')
  }
}

见: https ://github.com/axios/axios/issues/789#issuecomment -508114703

在接收端,如果您使用 Express,则需要multer 。 body-parser 不处理解析多部分请求。

@DespertaWeb没有文件时它不起作用。

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