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

IT技术 javascript dom google-chrome form-data
2021-03-04 00:06:28

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

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

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

6个回答

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

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

(参见MDN 文档

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

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

除了优秀的解决方案,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);
@Mahib 你是对的——Edge 的跟踪器 File构造函数上的问题 #9551546抛出Function Expected异常
2021-04-25 00:06:28
问题是您从剪贴板获取文件/blob。你所描述的与这个问题有关:stackoverflow.com/questions/27251953/...
2021-05-03 00:06:28
不适用于 IE,因为它仍然不支持 File 构造函数。
2021-05-06 00:06:28
@RobertK.Bell,我实际上检查了 Edge 并且它不起作用:(,然后我不得不改回 blob 构造函数。
2021-05-11 00:06:28
@Mahib MDN 关于File构造函数的文档表明 IE10 及更高版本都支持它。
2021-05-13 00:06:28

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

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

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

function getFileName() {
 // logic to generate file names
}
答案并没有回答最初的问题(除了“这里有一个替代方案”),而是为没有被问到的问题提供了答案,坦率地说,是题外话。
2021-04-24 00:06:28
@NielsAbildgaard:真的吗?它询问分配文件名,原始文件名是否符合有效文件名的条件?
2021-05-04 00:06:28
该问题不要求原始文件名。这个答案完全偏离目标。
2021-05-09 00:06:28

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

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

object_urlblob:{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 并去除任何破折号。

尚未对其进行测试,但这应该会提醒 blob 数据 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。我想要接收/设置的是在进行表单发布上传时附加到表单字段的文件名。
2021-04-19 00:06:28
然后我不知道没有服务器端通信的方法。
2021-04-24 00:06:28