Загрузка байтового массива в формате PDF на Angular - PullRequest
0 голосов
/ 06 ноября 2019

Я прочитал несколько сообщений 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, преобразует их в большой двоичный объект, а затем пытается сохранить его. Для fileType я пробовал 'application/pdf' и 'application/octet-stream', ни один не работает. Второй пример, который я пытался сохранить следующим образом:

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

Однако ни одна из этих функций не работает. Файл загружен, но когда вы открываете его, появляется ошибка, и ничего не отображается.

Я не уверен, что еще можно попробовать, но, надеюсь, кто-то может указать мне правильное направление.

1 Ответ

0 голосов
/ 07 ноября 2019

Если вы возвращаете StreamActionResult (или аналогичный ActionResult) из ASP.NET Core WebAPI, тогда вы сможете получить имя файла и тип файла из ответа HTTP.

  1. Создатьвспомогательная функция, которая извлекает fileName и fileType из ответа HTTP
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
  };
}
Позвоните в 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)
        )
      );
  }
}
В компоненте вызовите эту службу, подпишитесь на http-ответ и сохраните файл, используя file-saver npm library
import { saveAs } from 'file-saver';

private someMethod(): void {
 this.downloadsService.downloadPDF('/my/pdf/url').subscribe({
   next: downloadedFile => {
    saveAs(downloadedFile.blob, downloadedFile.fileName);
   }
 });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...