Safari converts the file to [Object] when pasted into FormData. How to fix?

I am posting a file in Javascript using the new FormData interface. When I submit a file using Safari 5.1.5 using "multipart / form-data", Safari forces the file into a string, and instead of sending the actual file content, it uploads [object Object]

.

Example:

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

      

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]

      

So my file is loading, but the content of the file, you guessed it, is [object Object]

.

What's going on in the world 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 doesn't work in Safari, so it didn't really help to include it in the question.

Edit 2

Object reference I object is associated with a drop action on a DOM element. Here's an example of extracting a file. Run the following after loading the DOM.

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);

      

+3


source to share


2 answers


It didn't strike me as relevant when I asked this question, but I figured it out. Before uploading the file using XMLHttopRequest, I called the jQuery method $.ajax

to call the endpoint in our backend to prepare the file.

In short: this is a bug in jQuery in Safari. I used a for loop to process a list of files and download them. I passed the file object as a parameter to the jQuery method $.ajax

so that the file object I needed was not overwritten as there were multiple loops. For example.

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

      

It turns out that jQuery is accidentally cloning an object file

in Safari. So instead of throwing it into a file when it is set to this.myFile

, it passes it to an object, thereby losing all of its special "file" capabilities. Other browsers seem to understand that the object is still a file despite this.



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

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

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

      

PS Go to file in jQuery tracker but just wanted to keep this here in case anyone else has a problem.

+2


source


file

should be String

, otherwise, if it's Object

his method toString()

is called when you add it to the form data object.



This is directly related to Blob

not working in Safari. For this to work in Safari, you need a way to force the file to String

itself, which is obviously not that easy (I don't even know if this is possible for security reasons?).

0


source







All Articles