angularjs BLOB URL的自定义名称

dnph8jn4  于 5个月前  发布在  Angular
关注(0)|答案(8)|浏览(86)

我们有一个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新手,希望我的问题听起来不是很天真。
感谢您发送编修。

23c0lvtd

23c0lvtd1#

简单回答,你不能。
这是一个指向浏览器内存的地址,它存储了你的blob,或者是一个指向原始文件的指针,如果用户通过输入type=file上传文件。
这是某种设计。你可以从同一个Blob创建多个这样的blobURL。如果他们使用一个文件名作为URI,你就不能。
从理论上讲,你应该可以动态地创建一个重定向到BlobURI的页面,你可以将这个重定向页面命名为you which。但这只是理论,我自己从来没有尝试过。
一个粗略的概念证明可以在this plunker中看到,很明显,你需要动态生成 * blobblock.html *,并将其名称更改为你想要的名称,并且强制它的内容头,以便浏览器认为它是一个html页面,如果你想摆脱.html的话。还要注意,它似乎不适用于pdf文件,这需要浏览器插件来触发,但是再做一些工作,也许可以破解一些东西。
但无论如何,我只是让随机网址,你的用户会越来越习惯它,因为越来越多的Web应用程序确实使用这个伟大的API。

8fq7wneg

8fq7wneg2#

在上面的else条件代码中,插入以下代码:

var file = new Blob([response.data], { type: 'application/pdf' });
var fileURL = URL.createObjectURL(file);

// create <a> tag dinamically
var fileLink = document.createElement('a');
fileLink.href = fileURL;

// it forces the name of the downloaded file
fileLink.download = 'pdf_name';

// triggers the click event
fileLink.click();

字符串

oewdyzsn

oewdyzsn3#

我正在寻找相同的,实际上你可以添加一个下载属性的链接,这将使Chrome的伎俩,我没有尝试在IE到目前为止。

<a href="urlBlobData" download="fileTest.csv">Your file</a>

字符串
这是Angular 5的一个例子

<a #link *ngIf="urlBlobData" [href]="urlData" target="_blank" rel="noopener" download="fileTest.csv">Your file</a>


希望这对你也有效。

xsuvu9jc

xsuvu9jc4#

2023年答案

对于那些希望在浏览器中使用类似pdf-lib的东西生成PDF,同时在用户单击浏览器内置PDF查看器上的下载/保存按钮时保留对提供给用户的默认文件名的控制的开发人员来说,这是一个令人沮丧的问题。

背景故事

我花了很多时间试图让PDF.js在Svelte中工作,这样它看起来就像默认的PDF查看器,只是下载按钮被覆盖。我遇到了一个又一个问题。一切似乎都对我不利,有旧的Stack Overflow答案和博客文章随意提到他们的项目使用PDF.js来显示PDF。事情已经改变了(比如Svelte不喜欢的顶级await的引入,以及关于默认查看器源代码发布的哲学上的改变)。我真的要在服务器上生成文件,这样我就可以控制文件名了吗?这是不可接受的。

概述

值得庆幸的是,你现在可以用Cache APIService Worker API组合来解决这个问题。它们被现代浏览器广泛支持,所以在兼容性方面不应该有任何问题。IE不支持它,很明显,但这真的不值得一提。

不幸的是,由于years-old bug的原因,这在基于Chromium的浏览器中无法正常工作

这种技术允许你利用基于浏览器的渲染,同时保持对文件名的控制,但需要注意的是,Chromium只会直接从服务器下载文件。如果你想在Chromium中看到这个问题,请在bug报告中打星星。

缓存API

基本上,您将文档添加到缓存中,并在服务器上为其分配一个不会妨碍任何其他文件的URL,然后在该高速缓存完成接受它时将iframesrc设置为URL。这将它存储在服务工作者可以找到它的位置,并告诉浏览器在那里查找它。由于您定义了URL,你还可以控制文件名(它是路径名的最后一段)。

Service Worker API

然后创建并注册一个service worker,它在从Internet获取文件之前检查该高速缓存是否存在。如果它在缓存中,那是因为你把它放在那里了,所以不用担心它会和随机文件混淆。当浏览器查找你刚才存储的文件时,它会找到并返回它,就像你从Internet下载的一样。

总结

在SvelteKit中注册Service worker很容易,只需在正确的位置创建一个文件即可,但在任何其他框架中创建和注册一个并不需要太多时间。您只需记住,浏览器将尝试挂起Service worker,迫使您在想要对其进行更改时清除站点数据。因此,最好避免将可能频繁更改的代码放入其中。

gg58donl

gg58donl5#

还有另一种可能的解决方案,可以探索,但它有它自己的问题。你实际上可以将你的blob url存储在浏览器cookie存储中,然后从另一个选项卡中检索它,当你创建共享worker时,它将连接到同一个worker。这里需要注意的是,当你的cookie值仍然设置时,你的blob可能会消失,所以当一个新的worker初始化时,它会默默失败。可能会有如果你测试了worker脚本是否成功运行,如果没有,删除cookie并重新创建blob,那么有一些方法可以缓解这种情况。但是,似乎没有一种可靠的方法可以知道worker是否从主线程运行,所以这会很棘手,但我怀疑如果你使用一些延迟/超时并等待来自worker的echo,那么这是可行的。

utugiqy6

utugiqy66#

你可以通过在下面添加来添加/传递文件名,但是它会下载文件,而不是在新选项卡中打开它,但至少用户会得到一个正确命名的文件,

//import and inject Renderer2
import { Renderer2 } from '@angular/core';

let downloadLink = this.renderer.createElement('a');

//this converts binary data to a pdf
downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, { type: 'application/pdf' }));

//you can pass filename here
   downloadLink.setAttribute('download', filename); 
   document.body.appendChild(downloadLink);
   downloadLink.click();

字符串

vd8tlhqk

vd8tlhqk7#

摘自如何使用window.open设置文件名
当然,这是下载文件,而不是在另一个选项卡中打开。

var downloadLink = document.createElement("a");
downloadLink.href = myBlob;
downloadLink.download = "myFile.pdf";

document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);

字符串

u4vypkhs

u4vypkhs8#

你可以简单地添加一个setTimeout来改变页面标题后,blob已经加载到新的标签如下-

newTab.location.href = URL.createObjectURL(blob); 
setTimeout(function() {
    newTab.document.title = blob.name;
}, 10);

字符串

相关问题