使用 XMLHttprequest 上传文件 - multipart/form-data 中缺少边界

Posted

技术标签:

【中文标题】使用 XMLHttprequest 上传文件 - multipart/form-data 中缺少边界【英文标题】:Uploading a file with XMLHttprequest - Missing boundary in multipart/form-data 【发布时间】:2012-09-03 02:45:09 【问题描述】:

我正在使用 XMLHttprequest 上传文件。 这是上传文件的JS函数:

var upload = function(file) 
    // Create form data
    var formData = new FormData();
    formData.append('file', file);

    var xhr = new XMLHttpRequest();

    // Open
    xhr.open('POST', this.options.action);

    // Set headers
    xhr.setRequestHeader("Cache-Control", "no-cache");
    xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
    xhr.setRequestHeader("Content-Type", "multipart/form-data");
    xhr.setRequestHeader("X-File-Name", file.fileName);
    xhr.setRequestHeader("X-File-Size", file.fileSize);
    xhr.setRequestHeader("X-File-Type", file.type);

    // Send
    xhr.send(formData);

在服务器端,在 upload.php 我是这样读取文件的:

file_put_contents($filename, (file_get_contents('php://input')));

一切正常,除了我收到一个 PHP 警告:

Missing boundary in multipart/form-data POST data in Unknown on line 0.

如果我删除此行: xhr.setRequestHeader("Content-Type", "multipart/form-data"); 警告消失。

这里应该是什么问题?

【问题讨论】:

尝试使用application/x-www-form-urlencoded 作为内容类型。或者忽略它,因为这是 ajax 请求发送的默认内容类型。 这可以工作,但对于大文件(甚至 5-600 KB),浏览器将冻结,因为它必须以“文本”格式发送文件。我必须使用multipart/form data 抱歉,忽略了文件上传位(不知道怎么做),但I think this might answer your queston,更具体地说:xhr.setRequestHeader("content-type","multipart/form-data; charset=utf-8; boundary=" + Math.random().toString().substr(2)); 应该可以解决问题 也试过这个解决方案。警告消失,但在这种情况下没有数据出现:file_get_contents('php://input') 为空。感谢您对 Elias 的帮助,如果您有任何其他想法,请告诉我。 我认为问题在于您的“Content-Type”标头中缺少边界。它应该类似于: Content-Type: multipart/form-data; boundary="same-as-the-boundary-in-request-body" 如果您省略设置“Content-Type”标头,这通常会为您创建 【参考方案1】:

这对我来说有点奇怪,但这是有效的:

// Open
xhr.open('POST', this.options.action, true);

// !!! REMOVED ALL HEADERS

// Send
xhr.send(formData);

在这种情况下,在服务器端我不会读取通过php://input 发送的文件,但该文件将位于$_FILES 数组中。

这解决了我的问题,但我仍然很好奇为什么现在出现在$_FILES 中的文件?

在 Chrome、Mozilla、Safari 和 IE10 中测试。

【讨论】:

The spec 解释(第 3 点)如果您没有手动指定任何内容,浏览器会设置正确的标题(包括 Content-Type 中正确的多部分边界指示)。该文件出现在 $_FILES 中,因为 PHP automatically puts files from multipart form uploads in that superglobal。 感谢您帮助我理解这一点。 我必须注释掉它才能工作xhr.setRequestHeader('Content-Type', 'multipart/form-data');......(但保留xhr.setRequestHeader('Accept', 'multipart/form-data')

以上是关于使用 XMLHttprequest 上传文件 - multipart/form-data 中缺少边界的主要内容,如果未能解决你的问题,请参考以下文章

使用 XMLHttpRequest 上传大文件时的进度条

使用 XMLHttprequest 上传文件 - multipart/form-data 中缺少边界

XMLHttpRequest + JSON + 文件上传 + axios

使用 XMLHttpRequest 将多个文件上传到 Express.js 3.5 服务器

并行文件上传 XMLHttpRequest 请求以及为啥它们不起作用

为啥 XMLHttpRequest 上传在 Firefox 中没有正确失败?