LA SITUATION:
Frontend: Vue. Backend: Laravel.
Dans l'application Web, je dois permettre à l'utilisateur de télécharger certains fichiers PDF:
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:
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
:
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!
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)
},
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