@EranosyanEduard

Как обеспечить загрузку pdf-файла, получаемого в ответе сервера, при помощи js?

Здравствуйте. Я - начинающий фронтендер, а действие происходит в рамка Vue-проекта.

Необходимо реализовать типичный функционал: пользователь отправляет запрос, в ответ на который приходит pdf-файл (начинается файл со строки %PDF-1.5), который и должен быть загружен на компьютер пользователя?

Погуглив, я нашел типичное решение, которое предлагается использовать в подобных ситуациях, но честно признаюсь, что не до конца понимаю, как оно работает, поэтому и не знаю как исправить то, что получаю либо пустой файл ли ошибку при открытии такого файла. Скажи пожалуйста, как обеспечить загрузку файла?

Прилигаю участок кода, который пытается обработать такой файл.

this.getSetOfDocumentsByContract(reqBody)
      .then(({ data }) => {
        const objURL = window.URL.createObjectURL(
          new Blob([...data], { type: "application/pdf" })
        );

        this.$refs.anchor.href = objURL;
        this.$refs.anchor.download = "file.pdf";
        this.$refs.anchor.click();

        setTimeout(() => {
          window.URL.revokeObjectURL(data);
        }, 100);

        this.propagateCustomEvt(evt.name);
      })
      .catch((reason) => (this.submitErrorText = "Непредвиденная ошибка"))
      .finally(() => (this.useAgreeButtonLoading = false));


Спасибо за ответ, но по какой-то причине использование конструктора Blob не позволяет достигнуть необходимого результата! А вот использование значения - результата вызова метода blob() на объекте, который представляет ответ от сервера приводит. В случае, если возможно, то объясните, пожалуйста, в чем тут дело?

<script>
      const btn = document.querySelector(".btn");

      btn.addEventListener("click", () => {
        fetch("someUrl", {
          method: "POST",
          headers: {
            "content-type": "application/json",
            "x-api-token": "someToken",
          },
          body: JSON.stringify({
            contractId: 80,
            document: 49904,
            download: true,
          }),
        }).then((v) => {
          v.blob().then((blob) => {
            // Использую метод slice, чтобы файл имел необходимый тип. 
            url = window.URL.createObjectURL(blob.slice(0, blob.size, "application/pdf"));

            const a = document.querySelector(".anchor");

            a.style.display = "none";
            a.href = url;
            a.download = "testFile.pdf";
            a.click();

            window.URL.revokeObjectURL(url);
          });
        });
      });
</script>
  • Вопрос задан
  • 2101 просмотр
Решения вопроса 1
Stalker_RED
@Stalker_RED
0. Берете откуда-то данные
1. Передаете их в URL.createObjectURL в нем и происходит вся магия - создается специальный объект, который браузер может "скачать".
2. Затем берете какую-то ссылку (или создаете новую), в ее href записываете этот url из предыдущего пункта
3. Делаете по ссылке .click() - и вызывается диалог сохранения файла.
4. Дело сделано, ссылку можно удалить, память можно очистить (revokeObjectURL)

Вот пример без внешних зависимостей:


Если у вас файл скачивается, но он то пустой, то ошибка при открытии - причина где-то в пункте 0, там где вы получаете или формируете pdf. И этот код вы не показываете.
Чтобы в этом удостоверится, смените тип на text/plain и в блоб передайте строку типа "hello world".
Попробуйте передать готовую PDF-ку, которая точно не пустая и нормально открывается.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы