如何为以FormData上传的Blob提供文件名?


76

我目前正在使用以下代码上传从剪贴板粘贴的图像:

// 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

有什么方法可以设置或接收客户端的此文件名,而无需进行服务器端的任何通信?

Answers:


146

对于Chrome,Safari和Firefox,只需使用以下命令:

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

(请参阅MDN文档


您在哪里注意到这个的???这很棒!关于chrome版本对此是否有支持的链接?
德米特里·索林

顺便说一句,这是在规范中:w3.org/TR/XMLHttpRequest2/#interface-formdata
Dmitrii Sorin

1
另外,我正在研究firefox错误以修复此问题,我已经修复了该错误,但是我遇到了一些“样式问题” bugzilla.mozilla.org/show_bug.cgi?id=690659(我目前没有时间修复此补丁,因此,如果有人想拿起它,我会非常满意)
Chiguireitor 2012年

@Chiguireitor还是不固定?
2012年

3
这是MDN的“兼容性表”。请注意,因为这个帖子的,追加与文件名有不同的浏览器和FF在所有浏览器摇摇欲坠支持:developer.mozilla.org/en-US/docs/Web/API/...
亚当

33

在这里添加它,因为它似乎不在这里。

除了出色的解决方案外,form.append("blob",blob, filename);您还可以将Blob转换为File实例:

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

1
问题是您从剪贴板中获取了文件/ blob。您所描述的与此问题有关:stackoverflow.com/questions/27251953/…–
jontro

9
在IE上无法使用,因为它仍然不支持File构造函数。
Mahib'Mar

@Mahib MDN关于File构造函数的文档表明,IE10及更高版本支持它。
罗伯特·贝尔

2
@ RobertK.Bell,我实际上在Edge上检查过,但没有起作用:(,然后我不得不改回blob构造函数
。– Mahib

1
@Mahib你是对的-Edge的跟踪器 File构造函数上的问题#9551546引发Function Expected异常
Robert K. Bell

3

由于您要将数据粘贴到剪贴板,因此没有可靠的方法来知道文件的来源及其属性(包括名称)。

最好的选择是提出自己的文件命名方案,并与Blob一起发送。

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

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

1
该问题不要求提供原始文件名。这个答案完全没有达到目标。
Niels Abildgaard 2014年

2
@NielsAbildgaard:真的吗?它询问分配文件名,并且原始文件名不符合有效文件名的资格吗?
Mrchief 2014年

1
答案没有回答原始问题(“替代方案”除外),而是提供了对未问到的问题的回答,坦率地说,是题外话。
Niels Abildgaard 2014年

2

该名称看起来是从对象URL GUID派生的。执行以下操作以获得名称所源自的对象URL。

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

object_url将采用与blob:{origin}{GUID}Google Chrome和moz-filedata:{GUID}Firefox中相同的格式。源是协议的协议+主机+非标准端口。例如,blob:http://stackoverflow.com/e7bc644d-d174-4d5e-b85d-beeb89c17743blob:http://[::1]:123/15111656-e46c-411d-a697-a09d23ec9a99。您可能要提取GUID并去除所有破折号。


1

还没有测试过,但是应该提醒blob数据网址:

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

这确实会警告blob作为数据网址。我想要接收/设置的是在上载表单后上传到表单字段的文件名。
jontro 2011年

那我不知道没有服务器端通信的方法。
JochenJung 2011年

0

这实际上取决于另一端的服务器配置方式以及用于处理Blob帖子的模块。您可以尝试在帖子的路径中放入所需的名称。

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

0

您在使用Google App Engine吗?您可以使用cookie(使用JavaScript制作)来维护文件名和从服务器接收的名称之间的关系。


0

使用Google Chrome浏览器时,您可以Google Filesystem API为此使用/滥用。在这里,您可以创建一个具有指定名称的文件,并将blob的内容写入其中。然后,您可以将结果返回给用户。

我还没有找到Firefox的好方法。可能需要一小段Flashdownloadify来命名blob。

IE10在中具有msSaveBlob()功能BlobBuilder

也许这更多是为了下载Blob,但这是相关的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.