如何给作为 FormData 上传的 Blob 一个文件名?

我目前正在上传剪贴板上粘贴的图像,代码如下:

// Turns out getAsFile will return a blob, not a file
var blob = event.clipboardData.items[0].getAsFile(),
form = new FormData(),
request = new XMLHttpRequest();
form.append("blob",blob);
request.open(
"POST",
"/upload",
true
);
request.send(form);

上传的表单字段的名称与此类似: Blob157fce71535b4f93ba92ac6053d81e3a

是否有任何方法来设置或接收这个文件名客户端,而不进行任何服务器端通信?

147691 次浏览

Haven't tested it, but that should alert the blobs data url:

var blob = event.clipboardData.items[0].getAsFile(),
form = new FormData(),
request = new XMLHttpRequest();


var reader = new FileReader();
reader.onload = function(event) {
alert(event.target.result); // <-- data url
};
reader.readAsDataURL(blob);

That name looks derived from an object URL GUID. Do the following to get the object URL that the name was derived from.

var URL = self.URL || self.webkitURL || self;
var object_url = URL.createObjectURL(blob);
URL.revokeObjectURL(object_url);

object_url will be formatted as blob:{origin}{GUID} in Google Chrome and moz-filedata:{GUID} in Firefox. An origin is the protocol+host+non-standard port for the protocol. For example, blob:http://stackoverflow.com/e7bc644d-d174-4d5e-b85d-beeb89c17743 or blob:http://[::1]:123/15111656-e46c-411d-a697-a09d23ec9a99. You probably want to extract the GUID and strip any dashes.

It really depends on how the server on the other side is configured and with what modules for how it handles a blob post. You can try putting the desired name in the path for your post.

request.open(
"POST",
"/upload/myname.bmp",
true
);

Since you're getting the data pasted to clipboard, there is no reliable way of knowing the origin of the file and its properties (including name).

Your best bet is to come up with a file naming scheme of your own and send along with the blob.

form.append("filename",getFileName());
form.append("blob",blob);


function getFileName() {
// logic to generate file names
}

Are you using Google App Engine? You could use cookies (made with JavaScript) to maintain a relationship between filenames and the name received from the server.

When you are using Google Chrome you can use/abuse the Google Filesystem API for this. Here you can create a file with a specified name and write the content of a blob to it. Then you can return the result to the user.

I have not found a good way for Firefox yet; probably a small piece of Flash like downloadify is required to name a blob.

IE10 has a msSaveBlob() function in the BlobBuilder.

Maybe this is more for downloading a blob, but it is related.

For Chrome, Safari and Firefox, just use this:

form.append("blob", blob, filename);

(see MDN documentation)

Adding this here as it doesn't seem to be here.

Aside from the excellent solution of form.append("blob",blob, filename); you can also turn the blob into a File instance:

var blob = new Blob([JSON.stringify([0,1,2])], {type : 'application/json'});
var fileOfBlob = new File([blob], 'aFileName.json');
form.append("upload", fileOfBlob);