admin管理员组文章数量:1426617
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]
.
Example:
var formdata = new FormData();
formdata.append("file", file);
var xhr = new XMLHttpRequest();
xhr.open("POST", "", true);
xhr.send(formdata);
What Safari ends up sending:
Origin: /
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:
------WebKitFormBoundarycLc5AIMWzGxu58n8
Content-Disposition: form-data; name="file"
[object Object]
My file is therefore uploaded, but the contents of the file are, you guessed it, [object Object]
.
What in the world is going on here? Is this a Safari bug?
Edit 1
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")
Unfortunately this does not work on Safari, so it didn't really help to include it in the question.
Edit 2
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);
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]
.
Example:
var formdata = new FormData();
formdata.append("file", file);
var xhr = new XMLHttpRequest();
xhr.open("POST", "https://example./upload", true);
xhr.send(formdata);
What Safari ends up sending:
Origin: https://example./
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./upload
------WebKitFormBoundarycLc5AIMWzGxu58n8
Content-Disposition: form-data; name="file"
[object Object]
My file is therefore uploaded, but the contents of the file are, you guessed it, [object Object]
.
What in the world is going on here? Is this a Safari bug?
Edit 1
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")
Unfortunately this does not work on Safari, so it didn't really help to include it in the question.
Edit 2
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);
Share
Improve this question
edited Mar 30, 2012 at 23:31
Dan Loewenherz
asked Mar 30, 2012 at 23:19
Dan LoewenherzDan Loewenherz
11.3k7 gold badges53 silver badges84 bronze badges
7
-
Need to see the code that defines your
file
variable on line 2. – Kevin Ennis Commented Mar 30, 2012 at 23:21 -
file
is provided by a drag and drop action. It's not dynamically created. In other browsers you can build aBlob
dynamically, but Safari isn't able to do that yet. – Dan Loewenherz Commented Mar 30, 2012 at 23:23 -
Question updated with code explaining how I get the
file
object. – Dan Loewenherz Commented Mar 30, 2012 at 23:37 - 1 Just put pretty much this exact code up on a quick and dirty page on my server and it seems to work okay. It justs posts to a PHP file that places the upload into a temp directory, then reads its contents and echoes it back. kevincennis./uploadtest. – Kevin Ennis Commented Mar 31, 2012 at 0:06
-
Whoa--so it does work. The plot thickens. This must have something to do with something I left out of the question (I didn't think it was relevant...I'm thinking it is now). I'm sending the file through postMessage to an iframe inside the page that receives the drop. The iframe contains the script that listens until the postMessage is received, creates the
FormData
, and then posts to the URL. – Dan Loewenherz Commented Mar 31, 2012 at 0:10
2 Answers
Reset to default 2This 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.
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;
// ...
});
}
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]);
}
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.
file
needs to be a String
, otherwise if it's an Object
its toString()
method gets called when you append it to the form data object.
This is directly related to Blob
not working in Safari. In order to get this working in Safari you would need a way to coerce the file into a String
yourself, which obviously isn't the easiest thing to do (don't even know if it's possible for security reasons?).
本文标签: javascriptSafari converts File to object Object when inserted into FormData How to fixStack Overflow
版权声明:本文标题:javascript - Safari converts File to [object Object] when inserted into FormData. How to fix? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745479770a2660124.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论