Safari 在插入 FormData 时将 File 转换为 [object Object].怎么修? [英] Safari converts File to [object Object] when inserted into FormData. How to fix?

查看:167
本文介绍了Safari 在插入 FormData 时将 File 转换为 [object Object].怎么修?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用新的 FormData 接口在 Javascript 中发布一个文件.当我使用 Safari 5.1.5 使用multipart/form-data"发送文件时,Safari 将文件强制转换为字符串,而不是发送实际的文件内容,而是发送 [object Object].

I'm posting a file in Javascript using the new FormData interface. When I send a file using Safari 5.1.5 using "multipart/form-data", Safari coerces the File into a string, and instead of sending the actual file contents, it sends [object Object].

示例:

var formdata = new FormData();
formdata.append("file", file);
var xhr = new XMLHttpRequest();
xhr.open("POST", "https://example.com/upload", true);
xhr.send(formdata);

Safari 最终发送的内容:

What Safari ends up sending:

Origin: https://example.com/
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.5 Safari/534.55.3
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarycLc5AIMWzGxu58n8
Referer: https://example.com/upload

------WebKitFormBoundarycLc5AIMWzGxu58n8
Content-Disposition: form-data; name="file"

[object Object]

我的文件因此被上传,但文件的内容,你猜对了,[object Object].

My file is therefore uploaded, but the contents of the file are, you guessed it, [object Object].

这到底是怎么回事?这是 Safari 的错误吗?

What in the world is going on here? Is this a Safari bug?

对于那些好奇如何动态生成 JS Blob 的人,这里有一个例子:

For those curious how to dynamically generate a JS Blob, here's an example:

var Builder = (window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder);
var builder = new Builder();
builder.append("hello, world");
var file = builder.getBlob("text/plain")

不幸的是,这在 Safari 上不起作用,因此将其包含在问题中并没有真正的帮助.

Unfortunately this does not work on Safari, so it didn't really help to include it in the question.

我引用的文件对象来自 DOM 元素上的放置操作.下面是如何检索文件的示例.加载 DOM 后运行以下命令.

The file object I reference is from a drop action on a DOM element. Here's an example for how to retrieve a file. Run the following after the DOM has loaded.

function cancel(e) {
    if (e.stopPropagation) {
        e.stopPropagation();
    }
    if (e.preventDefault) {
        e.preventDefault();
    }
}

function drop(e) {
    cancel(e);
    for (var i=0; i<e.dataTransfer.files.length; i++) {
        file = e.dataTransfer.files[i];
    }
}

var elem = document.getElementById("upload-area");
elem.addEventListener("drop", drop, false);

推荐答案

当我问这个问题时,这似乎无关紧要,但我想通了这一点.在使用 XMLHttopRequest 上传文件之前,我调用了 jQuery 的 $.ajax 方法来调用后端中的端点来准备文件.

This didn't seem relevant when I was asking the question, but I figured this one out. Before uploading the file using XMLHttopRequest, I called jQuery's $.ajax method to call an endpoint in our backend to prep the file.

简而言之:这是 Safari 上 jQuery 中的一个错误.我正在使用 for 循环来处理文件列表并上传它们.我将文件对象作为参数传递给 jQuery $.ajax 方法,这样我想要的文件对象就不会在执行多个循环时被重写.例如

In short: this is a bug in jQuery on Safari. I was using a for loop to process a list of files, and upload them. I passed a file object as a parameter to the jQuery $.ajax method so that the file object I wanted wouldn't be rewritten as multiple loops were executed. E.g.

for (i in files) {
    var file = files[i];
    $.ajax({
        method: "POST",
        myFile: file,
        success: function(response) {
            var file = this.myFile;
            // ...
    });
}

结果是 jQuery 碰巧在 Safari 中错误地克隆了 file 对象.因此,当设置为 this.myFile 时,它不是将其转换为文件,而是将其转换为对象,从而使其失去所有特殊的类文件"功能.尽管如此,其他浏览器似乎理解该对象仍然是一个文件.

Turns out that jQuery happens to clone the file object incorrectly in Safari. So instead of casting it to a file when set to this.myFile, it casts it into an object, thus making it lose all of its special "file-like" capabilities. The other browsers appear to understand that the object is still a file despite this.

答案是编写一个回调方法来处理文件上传.

The answer is to write a callback method to handle the file uploads.

function handleFile(file) {
    $.ajax({
        method: "POST",
        success: function(response) {
            // ...
    });
}

for (var i in files) {
    handleFile(files[i]);
}

附言打算将此提交给 jQuery 错误跟踪器,但只是想将其保留在此处,以防其他人遇到同样的问题.

P.S. Going to file this to the jQuery bug tracker, but just wanted to keep this here in case anyone else has the same issue.

这篇关于Safari 在插入 FormData 时将 File 转换为 [object Object].怎么修?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆