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

Posted

技术标签:

【中文标题】如何为作为 FormData 上传的 Blob 提供文件名?【英文标题】:How to give a Blob uploaded as FormData a file name? 【发布时间】:2011-10-03 15:29:00 【问题描述】:

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

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

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

【问题讨论】:

【参考方案1】:

对于 Chrome、Safari 和 Firefox,只需使用这个:

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

(见MDN documentation)

【讨论】:

你从哪里注意到这个???这很棒!有没有关于 chrome 版本对此支持的链接? 顺便说一句,这在规范中:w3.org/TR/XMLHttpRequest2/#interface-formdata 另外,我正在研究 firefox 错误来修复这个问题,我已经修复了它,但我有一些“样式问题”bugzilla.mozilla.org/show_bug.cgi?id=690659(我目前没有时间修复这个问题补丁,所以如果有人想拿起它,我会非常满意) @Chiguireitor 还没有修复? 这是来自 MDN 的“兼容性表”。请注意,在这篇文章中,附加文件名在除 Chrome 和 FF 之外的所有浏览器上都有不稳定的支持:developer.mozilla.org/en-US/docs/Web/API/…【参考方案2】:

在此处添加,因为它似乎不在此处。

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

【讨论】:

问题是您从剪贴板获取文件/blob。你所描述的与这个问题有关:***.com/questions/27251953/… 在 IE 上不起作用,因为它仍然不支持 File 构造函数。 @Mahib MDN's documentation on the File constructor 表明它受 IE10 及更高版本的支持。 @RobertK.Bell,我实际上检查了 Edge,但它不起作用:(,然后我不得不改回 blob 构造函数。 @Mahib 你是对的 ― issue #9551546 on Edge's tracker File 构造函数抛出 Function Expected 异常【参考方案3】:

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

最好的办法是提出自己的文件命名方案并与 blob 一起发送。

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

function getFileName() 
 // logic to generate file names

【讨论】:

问题不要求原始文件名。这个答案完全偏离目标。 @NielsAbildgaard:真的吗?它询问分配文件名,原始文件名不符合有效文件名吗? 答案没有回答原始问题(除了“这里有一个替代方案”),而是为没有被问到的问题提供了答案,坦率地说,是题外话。【参考方案4】:

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

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

object_url 在 Google Chrome 中将被格式化为 blob:originGUID,在 Firefox 中将被格式化为 moz-filedata:GUID。源是协议的协议+主机+非标准端口。例如,blob:http://***.com/e7bc644d-d174-4d5e-b85d-beeb89c17743blob:http://[::1]:123/15111656-e46c-411d-a697-a09d23ec9a99。您可能想要提取 GUID 并去除任何破折号。

【讨论】:

【参考方案5】:

尚未对其进行测试,但这应该会提醒 blobs 数据 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);

【讨论】:

这将提醒 blob 作为数据 url。我想要接收/设置的是在进行表单发布上传时附加到表单字段的文件名。 那我不知道没有服务器端通信的办法。【参考方案6】:

这实际上取决于另一端的服务器是如何配置的,以及它如何处理 blob 帖子的模块。您可以尝试将所需的名称放在帖子的路径中。

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

【讨论】:

【参考方案7】:

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

【讨论】:

【参考方案8】:

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

我还没有找到 Firefox 的好方法;可能需要一小块像 downloadify 这样的 Flash 来命名 blob。

IE10 在BlobBuilder 中有一个msSaveBlob() 函数。

也许这更多地用于下载 blob,但它是相关的。

【讨论】:

以上是关于如何为作为 FormData 上传的 Blob 提供文件名?的主要内容,如果未能解决你的问题,请参考以下文章

前端上传大型文件或超长数据的解决办法

如何为 BlobContainerClient 设置 dfs insted blob 端点

js实现大文件分片上传的方法

js实现大文件分片上传的方法

FormData、Blob、Map等几个对象概念

Canvas保存图片到七牛云