在Angular中将字节数组下载为PDF

时间:2019-11-06 19:04:00

标签: angular pdf

我已经阅读了几本与此相关的StackOverflow帖子,但尚未使它起作用。

我的后端是.NET Core应用程序,它返回byte[]供我下载PDF。这是返回的数据,首先通过正常调用API,然后将返回类型设置为blob

pdf card data return data

这两个呼叫是这样的:

this.http.get('/my/pdf/url').subscribe(data => console.log(data));

this.http.get('/my/pdf/url', { responseType: 'blob' }).subscribe(data => console.log(data));

在两种情况下,我都将返回数据发送到使用FileSaver包保存文件的服务中。对于第一个示例,我尝试像这样保存文件:

saveFile(buffer: any, fileName: string, fileType: string) {
    const data: Blob = new Blob([buffer], { type: fileType });
    FileSaver.saveAs(data, fileName);
}

它从API中获取数据,将其转换为Blob,然后尝试保存。对于fileType,我尝试了'application/pdf''application/octet-stream',但都没有一个。我试图保存的第二个示例是这样的:

savePdf(blob: Blob, fileName: string) {
    FileSaver.saveAs(<any>blob, fileName);
}

但是,这些功能都不起作用。文件已下载,但是当您打开它时,出现错误,并且不显示任何内容。

我不确定还可以尝试什么,但希望有人可以指出正确的方向。

1 个答案:

答案 0 :(得分:0)

如果您要从ASP.NET Core WebAPI返回StreamActionResult(或类似的ActionResult),那么您应该能够从HTTP响应中检索文件名和文件类型。

  1. 创建一个帮助函数,该函数从HTTP响应中检索fileName和fileType
export interface DownloadedFile {
  blob: Blob;
  fileName: string;
}

export function extractFileNameAndBlob(
  httpResponse: HttpResponse<ArrayBuffer>
): DownloadedFile {
  const headers = httpResponse.headers;
  const contentDisposition = headers.get("Content-Disposition");

  if (contentDisposition == null) {
    throw new Error(`Server Error: Cannot retrieve file name.
    Either Content-Dispostion header is not available or it is not exposed using Access-Control-Expose Header.`);
  }

  const fileNameItem = contentDisposition
    .split(";")
    .map(item => item.trim())
    .find(item => item.toLowerCase().startsWith("filename="));
  if (fileNameItem == null) {
    throw new Error(`Server didn't send a filename`);
  }

  let fileName = fileNameItem.split("=")[1];
  if (fileName.startsWith('"'))
    fileName = fileName.substring(1, fileName.length - 1);

  const contentType = headers.get("Content-Type");
  const blob = new Blob([httpResponse.body], { type: contentType });
  return {
    blob: blob,
    fileName: fileName
  };
}
  1. 从角度服务调用WebAPI
//  Angular Service
@Injectable()
export class DownloadsService {
  constructor(private httpClient: HttpClient) {}

  public downloadPDF(downloadUrl: string): Observable<DownloadedFile> {
    return this.httpClient
      .get(downloadUrl, { responseType: "arraybuffer", observe: "response" })
      .pipe(
        map((httpResponse: HttpResponse<ArrayBuffer>) =>
          extractFileNameAndBlob(httpResponse)
        )
      );
  }
}
  1. 在组件中,调用该服务,订阅http响应,然后使用file-saver npm库保存文件
import { saveAs } from 'file-saver';

private someMethod(): void {
 this.downloadsService.downloadPDF('/my/pdf/url').subscribe({
   next: downloadedFile => {
    saveAs(downloadedFile.blob, downloadedFile.fileName);
   }
 });
}