使用Javascript(或Angular)在每个部分上使用不同的Content-Type编写multipart/form-data

Yeo*_*Yeo 31 javascript forms file-upload multipartform-data angularjs

提出错误的问题,请参阅下面的更新

我需要将我的AngularJS项目与现有的RESTful API集成.这些API使用POST请求upload a file,并在请求中提交表单数据.不幸的是,其中一个表单输入需要进入Content-Type: Application/json.

在网络上搜索后,我只能POSTContent-Type: multipart/form-data其中每个部分不具有特定的MIME.如何 在Javascript中为每个部分组合我multipart/form-data的不同MIME

POST /api/v1/inventory
Host: localhost:8000
Origin: http://localhost:9000
Content-Type: multipart/form-data; boundary=------border

------border
Content-Disposition: form-data; name="owner"

john doe
------border
Content-Disposition: form-data; name="image"; filename="mybook.png"
Content-Type: image/png


------border
Content-Disposition: form-data; name="items"
Content-Type: application/json

{"name": "Book", "quantity": "12"}
------border--
Run Code Online (Sandbox Code Playgroud)

相关参考文献:

  1. https://developer.mozilla.org/en-US/docs/Web/Guide/Using_FormData_Objects
  2. REST - 带有JSON的HTTP Post Multipart
  3. http://code.activestate.com/recipes/578846-composing-a-postable-http-request-with-multipartfo/
  4. application/x-www-form-urlencoded或multipart/form-data?
  5. /sf/answers/635757041/

更新

为提出错误的问题而道歉.最初的问题是,我可以看到服务器调用逻辑的东西,

func POST(req):
     owner = req.owner // This is string
     image = req.image // This is file object
     itemQuantity = req.items.quantity // Items is an object with attribute quantity
     itemName = req.items.name // Items is an object with attribute name
Run Code Online (Sandbox Code Playgroud)

我还设法弄清楚如何提交这样的帖子请求.我将在下面发布我的答案.

再次抱歉提出错误的问题.

Ja͢*_*͢ck 56

根据文档FormData,您可以使用Blob构造函数追加具有特定内容类型的字段:

var formData = new FormData();

formData.append('items', new Blob([JSON.stringify({
    name: "Book",
    quantity: "12"
})], {
    type: "application/json"
}));
Run Code Online (Sandbox Code Playgroud)

经过仔细观察,结果发现它将发送如下部分:

Content-Disposition: form-data; name="items"; filename="blob"
Content-Type: text/json
Run Code Online (Sandbox Code Playgroud)

自己构建整个请求的唯一选择是传递字符串值:

formData.append('items', '{"name": "Book", "quantity": "12"}');
Run Code Online (Sandbox Code Playgroud)

不幸的是,这没有设置Content-Type标题.

  • 尽管它设置了 `Content-Type: 'application/json'`,但它仍然包装在 Blob 下。因此,API 拒绝了我的请求。https://gist.github.com/9gix/a79a70f9b56ed252c00e#file-multipart-form-data-L6-L11 (2认同)
  • Yeap 适用于 blob: var blob = new Blob([JSON.stringify(requestVo)], { type: "application/json" }) formData.append('data',blob); (2认同)

N-a*_*ate 7

除非我将标头设置为未定义,否则没有任何方法可以使其工作Content-Type。就我而言,我发布了一个文件和一些 json。

public uploadFile(code: string, file):angular.IHttpPromise<any>{
    var data = `{"query":"mutation FIRMSCORECARD_CALCULATE($code:String!){ FirmScorecardMutation{ BatchCalculate(Code:$code) }}","variables":{"code":"${code}"},"operationName":"FIRMSCORECARD_CALCULATE"}`;
    var formData = new FormData();
    formData.append('operations', data);
    formData.append('file', file, file.name);

    let config = {
        headers: {
            'Accept': 'application/json',
            'Content-Type': undefined
        }
    };
    let response = this.$http.post(this.graphqlUrl, formData, config);
    return response;
}
Run Code Online (Sandbox Code Playgroud)


Yeo*_*Yeo 6

错误#1:我错误地认为项目必须是json,以便我们可以调用它的属性.

解决方案:提交包含文件和格式对象的多部分请求非常简单.

form = new FormData();
form.append('items[name]', 'Book');
form.append('items[quantity]', 12);
form.append('image', imageFile);
form.append('owner', 'John Doe');
Run Code Online (Sandbox Code Playgroud)

因此请求标头和正文看起来像这样

POST /api/v1/inventory
Host: localhost:8000
Origin: http://localhost:9000
Content-Type: multipart/form-data; boundary=------border

------border
Content-Disposition: form-data; name="owner"

john doe
------border
Content-Disposition: form-data; name="image"; filename="mybook.png"
Content-Type: image/png


------border
Content-Disposition: form-data; name="items[name]"

Book
------border
Content-Disposition: form-data; name="items[quantity]"

12
------border--
Run Code Online (Sandbox Code Playgroud)