我们有一个Angular应用程序,它获取一些输入参数,并将它们发送到后端进行处理。处理结果是一个pdf文件,我们希望在新选项卡中打开它。
这样做的代码看起来与下面类似:
myService.getDocument(document)
.then(function(response) {
if (response.error) {
// Error handling goes here
} else {
var file = new BLob([response.data), {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
$window.open(fileURL, '_blank_');
}
});
字符串
一切正常,但浏览器中的URL显示一些随机生成的字符串如下:
blob:http://localhost:3000/85cad96e-e44e-a1f9-db97a96ed3fe
型
显然,这对最终用户来说并不是很好,我们更愿意显示一些对用户有意义的东西,比如下面的内容:
blob:ftp://localhost:3000/my_document_name_or_whatever
型
我是JS新手,Angular新手,HTML新手,希望我的问题听起来不是很天真。
感谢您发送编修。
8条答案
按热度按时间23c0lvtd1#
简单回答,你不能。
这是一个指向浏览器内存的地址,它存储了你的blob,或者是一个指向原始文件的指针,如果用户通过输入type=file上传文件。
这是某种设计。你可以从同一个Blob创建多个这样的blobURL。如果他们使用一个文件名作为URI,你就不能。
从理论上讲,你应该可以动态地创建一个重定向到BlobURI的页面,你可以将这个重定向页面命名为you which。但这只是理论,我自己从来没有尝试过。
一个粗略的概念证明可以在this plunker中看到,很明显,你需要动态生成 * blobblock.html *,并将其名称更改为你想要的名称,并且强制它的内容头,以便浏览器认为它是一个html页面,如果你想摆脱
.html
的话。还要注意,它似乎不适用于pdf文件,这需要浏览器插件来触发,但是再做一些工作,也许可以破解一些东西。但无论如何,我只是让随机网址,你的用户会越来越习惯它,因为越来越多的Web应用程序确实使用这个伟大的API。
8fq7wneg2#
在上面的else条件代码中,插入以下代码:
字符串
oewdyzsn3#
我正在寻找相同的,实际上你可以添加一个下载属性的链接,这将使Chrome的伎俩,我没有尝试在IE到目前为止。
字符串
这是Angular 5的一个例子
型
希望这对你也有效。
xsuvu9jc4#
2023年答案
对于那些希望在浏览器中使用类似
pdf-lib
的东西生成PDF,同时在用户单击浏览器内置PDF查看器上的下载/保存按钮时保留对提供给用户的默认文件名的控制的开发人员来说,这是一个令人沮丧的问题。背景故事
我花了很多时间试图让
PDF.js
在Svelte中工作,这样它看起来就像默认的PDF查看器,只是下载按钮被覆盖。我遇到了一个又一个问题。一切似乎都对我不利,有旧的Stack Overflow答案和博客文章随意提到他们的项目使用PDF.js
来显示PDF。事情已经改变了(比如Svelte不喜欢的顶级await的引入,以及关于默认查看器源代码发布的哲学上的改变)。我真的要在服务器上生成文件,这样我就可以控制文件名了吗?这是不可接受的。概述
值得庆幸的是,你现在可以用Cache API和Service Worker API组合来解决这个问题。它们被现代浏览器广泛支持,所以在兼容性方面不应该有任何问题。IE不支持它,很明显,但这真的不值得一提。
不幸的是,由于years-old bug的原因,这在基于Chromium的浏览器中无法正常工作
这种技术允许你利用基于浏览器的渲染,同时保持对文件名的控制,但需要注意的是,Chromium只会直接从服务器下载文件。如果你想在Chromium中看到这个问题,请在bug报告中打星星。
缓存API
基本上,您将文档添加到缓存中,并在服务器上为其分配一个不会妨碍任何其他文件的URL,然后在该高速缓存完成接受它时将
iframe
的src
设置为URL。这将它存储在服务工作者可以找到它的位置,并告诉浏览器在那里查找它。由于您定义了URL,你还可以控制文件名(它是路径名的最后一段)。Service Worker API
然后创建并注册一个service worker,它在从Internet获取文件之前检查该高速缓存是否存在。如果它在缓存中,那是因为你把它放在那里了,所以不用担心它会和随机文件混淆。当浏览器查找你刚才存储的文件时,它会找到并返回它,就像你从Internet下载的一样。
总结
在SvelteKit中注册Service worker很容易,只需在正确的位置创建一个文件即可,但在任何其他框架中创建和注册一个并不需要太多时间。您只需记住,浏览器将尝试挂起Service worker,迫使您在想要对其进行更改时清除站点数据。因此,最好避免将可能频繁更改的代码放入其中。
gg58donl5#
还有另一种可能的解决方案,可以探索,但它有它自己的问题。你实际上可以将你的blob url存储在浏览器cookie存储中,然后从另一个选项卡中检索它,当你创建共享worker时,它将连接到同一个worker。这里需要注意的是,当你的cookie值仍然设置时,你的blob可能会消失,所以当一个新的worker初始化时,它会默默失败。可能会有如果你测试了worker脚本是否成功运行,如果没有,删除cookie并重新创建blob,那么有一些方法可以缓解这种情况。但是,似乎没有一种可靠的方法可以知道worker是否从主线程运行,所以这会很棘手,但我怀疑如果你使用一些延迟/超时并等待来自worker的echo,那么这是可行的。
utugiqy66#
你可以通过在下面添加来添加/传递文件名,但是它会下载文件,而不是在新选项卡中打开它,但至少用户会得到一个正确命名的文件,
字符串
vd8tlhqk7#
摘自如何使用window.open设置文件名
当然,这是下载文件,而不是在另一个选项卡中打开。
字符串
u4vypkhs8#
你可以简单地添加一个
setTimeout
来改变页面标题后,blob已经加载到新的标签如下-字符串