web-dev-qa-db-fra.com

Vue + Laravel: Comment télécharger correctement un fichier PDF?

LA SITUATION:

Frontend: Vue. Backend: Laravel.

Dans l'application Web, je dois permettre à l'utilisateur de télécharger certains fichiers PDF:

  • J'ai besoin de Laravel pour prendre le fichier et le renvoyer en réponse à une requête API GET.
  • Puis dans mon Vue application web, je dois récupérer le fichier et le télécharger.

LE CODE:

API:

$file = public_path() . "/path/test.pdf";

$headers = [
    'Content-Type' => 'application/pdf',
];
return response()->download($file, 'test.pdf', $headers);

Application Web:

downloadFile() {
  this.$http.get(this.apiPath + '/download_pdf')
    .then(response => {
      let blob = new Blob([response.data], { type: 'application/pdf' })
      let link = document.createElement('a')
      link.href = window.URL.createObjectURL(blob)
      link.download = 'test.pdf'
      link.click()
    })
}

RÉSULTAT:

En utilisant ce code, je parviens à télécharger un fichier pdf. Le problème est que le pdf est vierge.

D'une manière ou d'une autre, les données ont été corrompues (pas un problème avec ce fichier pdf particulier, j'ai essayé avec plusieurs fichiers pdf - même résultat)

RÉPONSE DU SERVEUR:

La réponse elle-même du serveur est correcte:

enter image description here

PDF:

Le problème peut provenir du fichier pdf. Il semble définitivement que les données sont corrompues. Ceci est un extrait de la façon dont il ressemble à la response.data:

enter image description here

LA QUESTION:

Comment puis-je télécharger correctement un fichier pdf en utilisant Laravel pour l'API et Vue pour l'application Web?

Merci!

7
FrancescoMussi

SOLUTION:

Le mérite revient à @Sagar pour me diriger dans la bonne direction.

Le code ci-dessus était correct. Ce qui manquait, c'était d'ajouter le responseType approprié comme arraybuffer.

J'ai eu peur de ces ???? dans la réponse, et cela m'a induit en erreur. Ces points d'interrogation étaient corrects, car le pdf est une donnée binaire et est destiné à être lu par un lecteur approprié.

L'ARRAYBUFFER:

Et arraybuffer est précisément utilisé pour conserver les données binaires.

Voici la définition du site Web de mozilla:

L'objet ArrayBuffer est utilisé pour représenter un tampon de données binaires brutes de longueur fixe générique. Vous ne pouvez pas manipuler directement le contenu d'un ArrayBuffer; au lieu de cela, vous créez l'un des objets de tableau typé ou un objet DataView qui représente le tampon dans un format spécifique et l'utilisez pour lire et écrire le contenu du tampon.

Et la chaîne ResponseType indique le type de la réponse. En lui indiquant un tampon de tableau, il traite ensuite les données en conséquence.

Et juste en ajoutant le responseType, j'ai réussi à télécharger correctement le fichier pdf.

LE CODE:

Ceci est corrigé Vue code (exactement comme avant, mais avec l'ajout du responseType):

downloadFile() {
  this.$http.get(this.appApiPath + '/testpdf', {responseType: 'arraybuffer'})
    .then(response => {
      let blob = new Blob([response.data], { type: 'application/pdf' })
      let link = document.createElement('a')
      link.href = window.URL.createObjectURL(blob)
      link.download = 'test.pdf'
      link.click()
    })
}

MODIFIER:

Il s'agit d'une solution plus complète qui prend en compte le comportement des autres navigateurs:

downloadContract(booking) {
  this.$http.get(this.appApiPath + '/download_contract/' + booking.id, {responseType: 'arraybuffer'})
    .then(response => {
      this.downloadFile(response, 'customFilename')
    }, response => {
      console.warn('error from download_contract')
      console.log(response)
      // Manage errors
      }
    })
},

downloadFile(response, filename) {
  // It is necessary to create a new blob object with mime-type explicitly set
  // otherwise only Chrome works like it should
  var newBlob = new Blob([response.body], {type: 'application/pdf'})

  // IE doesn't allow using a blob object directly as link href
  // instead it is necessary to use msSaveOrOpenBlob
  if (window.navigator && window.navigator.msSaveOrOpenBlob) {
    window.navigator.msSaveOrOpenBlob(newBlob)
    return
  }

  // For other browsers:
  // Create a link pointing to the ObjectURL containing the blob.
  const data = window.URL.createObjectURL(newBlob)
  var link = document.createElement('a')
  link.href = data
  link.download = filename + '.pdf'
  link.click()
  setTimeout(function () {
    // For Firefox it is necessary to delay revoking the ObjectURL
    window.URL.revokeObjectURL(data)
  }, 100)
},
16
FrancescoMussi

Vous ne pourrez pas faire le téléchargement de Laravel vers Vue car les deux fonctionnent sur des ports différents, je suppose.

Même si vous essayez quelque chose comme ça.

public function getDownload()
    {
        //PDF file is stored under project/public/download/info.pdf
        $file= public_path(). "/download/info.pdf";

        $headers = [
              'Content-Type' => 'application/pdf',
           ];

    return response()->download($file, 'filename.pdf', $headers);
    }

Cela n'aidera pas car vous envoyez des en-têtes au port Laravel Essayez d'utiliser Vue js bibliothèques et essayez d'envoyer ce contenu pdf sur la bibliothèque

Essayez ceci Obtenez de l'aide d'ici

5
Sagar Ahuja