使用 axios 在 POST multipart/form-data 请求中发送文件和 json

Posted

技术标签:

【中文标题】使用 axios 在 POST multipart/form-data 请求中发送文件和 json【英文标题】:sending file and json in POST multipart/form-data request with axios 【发布时间】:2018-11-19 07:31:45 【问题描述】:

我正在尝试在同一个多部分 POST 请求中向我的 REST 端点发送一个文件和一些 json。请求是使用 axios 库直接从 javascript 发出的,如下方法所示。

doAjaxPost() 
    var formData = new FormData();
    var file = document.querySelector('#file');

    formData.append("file", file.files[0]);
    formData.append("document", documentJson);

    axios(
        method: 'post',
        url: 'http://192.168.1.69:8080/api/files',
        data: formData,
    )
    .then(function (response) 
        console.log(response);
    )
    .catch(function (response) 
        console.log(response);
    );

但是,问题是当我在网络选项卡中检查 chrome 开发人员工具中的请求时,我发现 document 没有 Content-Type 字段,而 file 字段 Content-Typeapplication/pdf(我' m 发送一个 pdf 文件)。

在服务器上Content-Typedocumenttext/plain;charset=us-ascii

更新:

我通过邮递员发送了一个正确的请求,将document 作为.json 文件发送。虽然我发现这只适用于 Linux/Mac。

【问题讨论】:

【参考方案1】:

要设置内容类型,您需要传递一个类似文件的对象。您可以使用Blob 创建一个。

const obj = 
  hello: "world"
;
const json = JSON.stringify(obj);
const blob = new Blob([json], 
  type: 'application/json'
);
const data = new FormData();
data.append("document", blob);
axios(
  method: 'post',
  url: '/sample',
  data: data,
)

【讨论】:

我在任何地方都找不到解决方案这么久,而您几乎立即就得到了正确的答案。非常感谢! :) 你在哪里附加文件?此代码示例中是否缺少它? @ElectRocnic — 整个答案是关于在内存中生成 JSON 文件并附加它。我没有重复从文件输入中读取文件的逻辑,因为问题与此无关(以及演示该问题的代码已经在问题中)。 谢谢我让它运行了。唯一缺少的行是我添加的formData.append("file", file),它对我有用:) 非常有用。谢谢。在服务器上,如何解压“文档”?我看到 blob 和文件一样被上传。我不希望上传 blob。我只需要解压“文档”。我如何做到这一点?【参考方案2】:

试试这个。

doAjaxPost() 
    var formData = new FormData();
    var file = document.querySelector('#file');

    formData.append("file", file.files[0]);
    // formData.append("document", documentJson); instead of this, use the line below.
    formData.append("document", JSON.stringify(documentJson));

    axios(
        method: 'post',
        url: 'http://192.168.1.69:8080/api/files',
        data: formData,
    )
    .then(function (response) 
        console.log(response);
    )
    .catch(function (response) 
        console.log(response);
    );

您可以在后端解码这个字符串化的 JSON。

【讨论】:

但后端接收 blob 作为对象字符串,如 '[object Object]'。【参考方案3】:

您只需将正确的标头添加到您的请求中

axios(
  method: 'post',
  url: 'http://192.168.1.69:8080/api/files',
  data: formData,
  header: 
            'Accept': 'application/json',
            'Content-Type': 'multipart/form-data',
          ,
    )

【讨论】:

我的标头字段已正确设置。问题是负载中的Content-Type 是的,正是在请求中,它应该是多部分/表单数据时写入文本/纯文本 这将覆盖多部分数据的 Content-Type,丢弃边界参数并破坏服务器解析它的能力。它不会对该多部分数据的“文档”部分的 Content-Type 产生任何影响。

以上是关于使用 axios 在 POST multipart/form-data 请求中发送文件和 json的主要内容,如果未能解决你的问题,请参考以下文章

使用 axios POST 请求将 JSON 数据作为 multipart/form-data 发送

使用axios发送post请求,将JSON数据改为为form类型

使用axios发送post请求,将JSON数据改为为form类型

axios使用

如何在提交侦听器上传递表单数据,以便 axios 可以发布表单数据?

VueJS、Axios、Laravel - 捕获错误