简体   繁体   English

在POST到服务器之前如何正确地将文件附加到formData?

[英]How to correctly attach file to formData before POSTing to server?

I've been following this FormData tutorial here , however have yet to understand how the formData object works. 我一直在这里关注这个FormData教程 ,但是还没有理解formData对象是如何工作的。

My input form 我的输入表格

在此输入图像描述

<input type="file" id="file-id" class="w300px rounded4px" name="file" placeholder="PDF file">
<button class="btn-upload-pdf" ng-click="asub.uploadPDF()">Upload</button>

Here is the upload button function: 这是上传按钮功能:

this.uploadPDF = () => {
    const formData = new FormData();
    const fileInput = document.getElementById('file-id');
    const file = fileInput.files[0];
    formData.append('pdf-file', file);
    console.log('formData', formData)

    return ApiFactory.insightPDF(formData).then((res) => {
        console.log('res', res);
        return res;
    });
};

When I log out the fileInput object .files[0] I see the file I just attached: 当我注销fileInput对象.files[0]我看到我刚刚附加的文件:

在此输入图像描述

It would seem to mean that this object should be enough to send along to the POST. 这似乎意味着这个对象应该足以发送到POST。 However this is the next step: 然而,这是下一步:

formData.append('pdf-file', file);

I log out formData before I send it into my Factory and this is the result, I don't see the key pdf-file or that PDF anywhere, just a bunch of methods? 我在将它发送到工厂之前注销了formData ,这就是结果,我没有在任何地方看到关键的pdf-file或PDF,只是一堆方法? Where does the file get appended too? 文件在哪里也附加了? How does formData contain the actual PDF? formData如何包含实际的PDF?

在此输入图像描述

I need to attach something from the formData object I presume: 我需要从我假设的formData对象中附加一些东西:

The Factory that makes the POST request 发出POST请求的Factory

const insightPDF = (formData) => {
    console.log(' formData', formData)
    return $http.post('/app/api/insights_pdf', formData).then((res) => {
        console.log('PDF uploaded res', res)
        return res;
    }).catch(apiError);
};

Set Content-Type: undefined 设置Content-Type: undefined

When posting objects created by the FormData API it is important to set the content type header to undefined . 发布FormData API创建的对象时,将内容类型标头设置为undefined非常重要。

const insightPDF = (formData) => {
    console.log(' formData', formData)
    var config = { headers: {'Content-Type': undefined} };
    return $http.post('/app/api/insights_pdf', formData, config)
     .then((res) => {
        console.log('PDF uploaded res', res)
        return res;
    }).catch(apiError);
};

Normally the AngularJS framework, automatically add the content type header as application/json which overrides the content type set by the XHR Send() method . 通常,AngularJS框架会自动将内容类型标头添加为application/json ,它会覆盖XHR Send()方法设置的内容类型。 When the XHR API sends a FormData object , it automatically sets the content type to multipart/form-data with the proper boundary. XHR API发送FormData对象时 ,它会自动将内容类型设置为具有适当边界的multipart/form-data

From the Docs: 来自Docs:

The $http service will automatically add certain HTTP headers to all requests $ http服务将自动为所有请求添加某些HTTP标头

To explicitly remove a header automatically added via $httpProvider.defaults.headers on a per request basis, Use the headers property, setting the desired header to undefined . 要基于每个请求显式删除通过$httpProvider.defaults.headers自动添加的标头,请使用headers属性,将所需标头设置为undefined For example: 例如:

 var req = { method: 'POST', url: 'http://example.com', headers: { 'Content-Type': undefined }, data: { test: 'test' } } 

— AngularJS $http Service API Reference - Setting HTTP Headers - AngularJS $ http服务API参考 - 设置HTTP标头

FormData objects like blobs are host-defined objects non-native to JavaScript. blob这样的FormData对象是非JavaScript原生的主机定义对象。 Not all of their properties can be seen by console.log or console.dir . 并非console.logconsole.dir可以看到它们的所有属性。 Files are a special type of blob. 文件是一种特殊类型的blob。 The data is not necessarily loaded from disk. 数据不一定从磁盘加载。 Usually, the data is streamed from disk only when needed by a specific API. 通常,仅在特定API需要时才从磁盘流式传输数据。


Avoid Extra Overhead -- Send files directly 避免额外开销 - 直接发送文件

Content in multipart/form-data uses base64 encoding which adds 33% extra overhead. multipart/form-data使用base64编码 ,这增加了33%的额外开销。 If uploading only one file, it is more efficient to send the file blob directly. 如果只上传一个文件,则直接发送文件blob更有效。

//MORE Efficient; Avoids base64 encoding overhead

const insightPDF = (dataObject) => {
    var config = { headers: {'Content-Type': undefined} };
    return $http.post('/app/api/insights_pdf', dataObject, config)
     .then((res) => {
        console.log('PDF uploaded res', res)
        return res;
    }).catch(apiError);
};

var file = inputElem[0].files[0];
insightPDF(file);

If the server can accept binary content directly, it is best to send files that way. 如果服务器可以直接接受二进制内容,最好以这种方式发送文件。 The XHR API will automatically set the content type to that of the file. XHR API将自动将内容类型设置为文件的内容类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM