我正在使用文件api和xhr2规范。我使用FormData
和$.ajax(options)
创建了一个上传器(由旧浏览器支持flash),其中带有File
的FormData对象是options.data
对象的一部分。一切正常。
现在我决定删除FormData
,因为浏览器支持较弱。除了
var xhr = new XMLHttpRequest();
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.setRequestHeader("X-File-Name", file.name);
xhr.send(file);
哪些不会返回我可以在递归函数中使用的Promise。
我的代码是这样的:
startUpload: function() {
var that = this;
that.recurseSend(that.queue);
},
_initProgressListener: function (options, file) {
var that = this;
var xhr = $.ajaxSettings.xhr();
options.contentType = 'multipart/form-data';
options.processData = false;
options.type = 'POST';
// WHAT TO DO HERE TO avoid FormData???? What ever I put into options.data - fails
/* THIS WOULD WORK
var formData = new FormData();
formData.append('file', file);
options.data = formData;
*/
if (xhr.upload && xhr.upload.addEventListener) {
xhr.upload.addEventListener('progress', function (e) {
that._onProgress(e, file);
}, false);
options.xhr = function () {
return xhr;
};
}
},
recurseSend: function (queue) {
var file = queue.pop();
if(file != undefined) {
var that = this;
var options = that.options;
that._initProgressListener(options, file);
var send = function() {
jqXHR = ($.ajax(options)).done(function(result, textStatus, jqXHR) {
that._onDone(result, textStatus, jqXHR, file);
queue.stats['successful_uploads']++;
}).fail(function(jqXHR, textStatus, errorThrown) {
that._onFail(jqXHR, textStatus, errorThrown, file);
queue.stats['upload_errors']++;
}).always(function(result, textStatus, jqXHR) {
that._onAlways(result, textStatus, jqXHR, file);
queue.stats['files_queued']--;
that.recurseSend(queue);
});
return jqXHR;
};
this._beforeSend(file);
return send();
}
},
要简短,$.ajax(options)
如果xhr.send(formData)
解析为options.data = FormData
,但如何将其解析为xhr.send(file)
?
编辑:我正在玩它,如果我设置options.data = file;然后$ .ajax(options)执行xhr.send(theFile);但错误Error: INVALID_STATE_ERR: DOM Exception 11
并且请求作为POST multipart / form-data请求发送,但没有包含文件的multipart body
如果我将它放入options.data = {file: file};
,无论processData
属性是否设置为true,它都会被序列化。
答案 0 :(得分:2)
您可以使用FileReader
或类似API从HTML5文件数据中手动生成上传的MIME数据。退房:https://github.com/coolaj86/html5-formdata。虽然这取决于getAsBinary()
,但这会更多或更少 - 将其更改为也能够使用FileReader
和readAsBinaryString()
可能会更加跨浏览器兼容。
请注意,这在IE7 / 8中仍然无法正常工作,正如其他人所说的那样,如果不诉诸Flash或iframe,就无法做到这一点。话虽这么说,如果你使用File,大概你也不关心IE7或IE8 ......
答案 1 :(得分:0)
每当您处理从用户计算机上传任意数据时,答案通常是“不,如果可以,那就是错误”。
这让我觉得有些违反安全规定的行为。您无法更改文件输入控件的值或执行许多其他操作,包括读取文件的真实路径或其内容。此外,在某些平台上,你甚至没有文件大小(IE,我在看你),没有弹出一些安全对话框(通过activex控件)。鉴于所有这些问题,我可能会说,即使您确实找到了解决方案,它也可能被视为未来的错误并被删除或更改。
换句话说,除非您找到明确支持它的信誉良好的来源,否则我认为这不是一件安全的事情......就像chrome dev博客一样。
答案 2 :(得分:0)
我自己使用了valums ajax uploader。你可以从这里得到它: http://valums.com/ajax-upload/。它工作得非常好。我不知道确切的实现细节,但这里有一个非常简短的描述:
“此插件使用XHR上传多个文件,其中包含FF3.6 +,Safari4 +,Chrome中的进度条,并在其他浏览器中回退到隐藏的基于iframe的上传,从而在各处提供良好的用户体验。”
所以听起来它非常接近你想要的东西。这是从服务器的角度(从server / readme.txt)描述它的工作方式的另一部分信息:
对于IE6-8,Opera,其他浏览器的旧版本,您获取该文件 您通常使用常规的表单上传。
对于使用进度条上传文件的浏览器,您需要获取原始文件 发布数据并将其写入文件。
因此需要在服务器端进行特殊处理。幸运的是,它带有几个参考服务器端实现(perl,php和java),所以不应该太麻烦。快乐的ajax上传:)
答案 3 :(得分:-1)
How can I upload files asynchronously?
如果不通过iFrame,似乎无法做到这一点。在我链接的答案中似乎有工作片段,以及为你做的几个插件。
* 编辑,因为我收到了评论 *
是的,有可能 - http://caniuse.com/xhr2 - 虽然没有低于10的IE支持..
下载教程:
http://www.html5rocks.com/en/tutorials/file/xhr2/
http://www.profilepicture.co.uk/ajax-file-upload-xmlhttprequest-level-2/