DootyBooty
DootyBooty

Reputation: 67

Setting a filename to a blob before uploading it

I need to upload image files to the server using blob, but the name of the file after uploading is always set to "blob" or, when downloading, the name of the source code file + .jpg. My code works on Chrome, but I need it to work on IE10 and unfortunately I don't know how.

What I do is this:

function uploadBlob() {
    var fileName = //insert method to get the original filename of the file uploaded here...

    var blob = dataURItoBlob(dataURL); //this method gets an image, compresses it and returns it as blob

    var blob2 = new Blob([blob], { type: "image/jpeg" });
                      blob2.lastModifiedDate = new Date();
                      blob2.name = fileName;

    return blob2;
}

This would be much easier with File Constructor, but IE and Edge don't support it. The function needs to return a file or a blob, and with my current code it uploads to the server just fine, it's just the file name isn't right. How can I get around this?

Upvotes: 1

Views: 5340

Answers (3)

Kaiido
Kaiido

Reputation: 136638

You don't show how you are sending this Blob to your server, but there aren't too many ways, so let's explore them:

The most usual is to send you Blob as part of a multipart form-data request.

To do so, you'll either use the HTML <form> post internal methods, or AJAX, however, while it's now possible through hacks to set arbitrary data in such an HTML <form>, these hacks would require you set a filename, so we can easily assume you're not in this case.
So this leaves us with AJAX.

To send such a multipart request with AJAX, you are probably using a FormData object and its append() method.
This method, when used with a Blob (or a File) accepts three parameters:

  • The field-key by which you'll be able to access the data from your server (this corresponds to the name attribute of an <input>in a <form>).
  • The Blob (or File), that will set its binary data as field-value.
  • An optional file name. (For Files, their name property is used if this param is not set.)

So in code that would be

const your_blob = new Blob(['some data'], { type: 'text/plain'} );

const formData = new FormData();
formData.append('file_key', your_blob, 'myfile.txt');

/* Then you can send this FormData through AJAX
 *   const xhr = new XMLHttpRequest();
 *   xhr.open('POST', your_url);
 *   xhr.send(formData);
 * or
 *   fetch( {
 *     method: "POST",
 *     url: your_url,
 *     body: formData
 *   } );
 */
// for this demo we'll just print the request's content:
new Response(formData)
  .text()
  .then(console.log);

An other option to send this Blob to your server is to use AJAX to send the binary data directly as a raw POST request.
This can be done by passing your Blob directly to the XMLHttpRequest.send() method, or as the body property of fetch request.

In these case, the file name will be discarded, and only the Content-Type will be set by the browser.
So to pass the file name along this kind of request, we need to use a custom HTTP header.

const xhr = new XMLHttpRequest();
xhr.open('POST', your_url);
xhr.setRequestHeader('X-filename', your_filename);
xhr.send(your_blob);

// or

fetch( your_url, {
  method: "POST",
  headers: { "X-filename": your_filename },
  body: your_blob
} );

And then you'd have to retrieve this header's content from your server-side.

Upvotes: 1

Zhi Lv
Zhi Lv

Reputation: 21383

When you upload the file, you could create a FormData object which contains the file name and file content (the blob), then post to the server, and store them in the same data table with different columns.

When we download file we could get the file name and file content, then, after getting data from the server side, you could refer to the following code to download file:

//IE11 and Edge browser support
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
   return navigator.msSaveOrOpenBlob(file.content, file.name);
    }
    else{
        var link = document.createElement('a');
        link.href = window.URL.createObjectURL(file.content);
        link.download = file.name;
        document.body.appendChild(link);
        link.dispatchEvent(new MouseEvent('click', {bubbles: true, cancelable: true, view: window}));
        link.remove();
        window.URL.revokeObjectURL(link.href);
    }

If using IE and Edge browser, we could use the msSaveOrOpenBlob or the msSaveBlob method to download the file, for other browser, we could create an html element and use the download attribute to download the file.

Upvotes: 1

Lajos Arpad
Lajos Arpad

Reputation: 76444

Your file upload is part of a request. You can pass filename as a separate parameter of the same request. If that's not an option for you, then you can create a request before uploading the blob, by sending in the filename and set a session variable which therefore will be known upon the next request, when the blob is uploaded. However, if possible, pass a filename parameter separately to the request, not just as the name of the blob, as it appears to be the bug in your case.

Upvotes: 0

Related Questions