Ich möchte eine pdf-Datei mit herunterladen axios und auf Platte (serverseitig) mit speichern fs.writeFileIch habe versucht:
axios.get('https://xxx/my.pdf', {responseType: 'blob'}).then(response => {
fs.writeFile('/temp/my.pdf', response.data, (err) => {
if (err) throw err;
console.log('The file has been saved!');
});
});
Die Datei wird gespeichert, aber der Inhalt ist beschädigt …
Wie speichere ich die Datei richtig?
Sie erhalten das Konsolenprotokoll “Die Datei wurde gespeichert” und die Datei wird erstellt und nur der Inhalt ist falsch?
– Roland Starke
27. März 2019 um 10:19 Uhr
Wo rufst du axios.get auf? es wird nicht darauf gewartet, dass die Datei geschrieben wird. Versprechen Sie besser die fs oder verwenden Sie fs-extra oder verwenden Sie versprochene Methoden von fs. und verwenden Sie wie return fs.writeFile(…)
– AZ_
27. März 2019 um 10:21 Uhr
@RolandStarke ja, die Datei wird gespeichert
– ar099968
27. März 2019 um 10:27 Uhr
Ich habe unten einen saubereren Ansatz zur Lösung des Problems mit Node-Stream-Pipelines veröffentlicht. Es basiert auf demselben Konzept, das die akzeptierte Antwort vorschlägt. stackoverflow.com/a/64925465/3476378
– Aman Saraf
20. November 2020 um 7:39 Uhr
csotiriou
Tatsächlich glaube ich, dass die zuvor akzeptierte Antwort einige Mängel aufweist, da sie den Writestream nicht richtig verarbeitet. Wenn Sie also “then()” aufrufen, nachdem Axios Ihnen die Antwort gegeben hat, erhalten Sie am Ende eine teilweise heruntergeladene Datei.
Dies ist eine geeignetere Lösung, wenn Sie etwas größere Dateien herunterladen:
export async function downloadFile(fileUrl: string, outputLocationPath: string) {
const writer = createWriteStream(outputLocationPath);
return Axios({
method: 'get',
url: fileUrl,
responseType: 'stream',
}).then(response => {
//ensure that the user can call `then()` only when the file has
//been downloaded entirely.
return new Promise((resolve, reject) => {
response.data.pipe(writer);
let error = null;
writer.on('error', err => {
error = err;
writer.close();
reject(err);
});
writer.on('close', () => {
if (!error) {
resolve(true);
}
//no need to call the reject here, as it will have been called in the
//'error' stream;
});
});
});
}
Auf diese Weise können Sie anrufen downloadFile()Anruf then() auf das zurückgegebene Versprechen und stellen Sie sicher, dass die heruntergeladene Datei vollständig verarbeitet wurde.
Wenn Sie eine modernere Version von NodeJS verwenden, können Sie stattdessen Folgendes versuchen:
import * as stream from 'stream';
import { promisify } from 'util';
const finished = promisify(stream.finished);
export async function downloadFile(fileUrl: string, outputLocationPath: string): Promise<any> {
const writer = createWriteStream(outputLocationPath);
return Axios({
method: 'get',
url: fileUrl,
responseType: 'stream',
}).then(response => {
response.data.pipe(writer);
return finished(writer); //this is a Promise
});
}
Das ist richtig und löst genau das Problem im Zusammenhang mit Partial data error
– Giorgio Andretti
27. April 2020 um 13:12 Uhr
Dies sollte die akzeptierte Antwort sein. Es hat den teilweisen Download-Fehler behoben
– Arizona
12. Mai 2020 um 18:10 Uhr
Ich habe unten einen saubereren Ansatz zum gleichen Konzept Ihrer Verwendung von Stream-Pipelines veröffentlicht: stackoverflow.com/a/64925465/3476378.
– Aman Saraf
20. November 2020 um 7:38 Uhr
Ich bin mir nicht sicher, ob ich folgen kann. Wenn Bytes heruntergeladen werden, werden sie in eine Datei gestreamt, und sobald alle Bytes gestreamt wurden, endet das Promise und der Rest des Anwendungsablaufs wird fortgesetzt. Das ‘then’ im Beispiel wird aufgerufen, bevor die Datei vollständig heruntergeladen wurde – sehen Sie in der Dokumentation nach stream AntwortTyp von Axios.
– csotiriou
27. Februar 2021 um 22:17 Uhr
response.data.pipe ist keine Funktion
– rendom
12. Juni 2021 um 5:56 Uhr
Sie können einfach verwenden response.data.pipe und fs.createWriteStream um die Antwort an die Datei weiterzuleiten
Diese Antwort ist nicht vollständig, denn wenn Sie einige größere Dateien herunterladen, gibt Ihnen die Pipe mehr als ein Ereignis. Dieser Code wartet nicht, bis die gesamte Datei heruntergeladen wurde, bevor man anrufen kann then darauf. Werfen Sie einen Blick auf meine Lösung, um herauszufinden, was ich für eine vollständigere Lösung halte.
– csotiriou
17. April 2020 um 10:33 Uhr
response.data.pipe ist keine Funktion
– Murat Serdar Akkuş
11. Juni 2020 um 1:36 Uhr
Wenn die Datei nicht auf den lokalen Speicher heruntergeladen werden soll, wie das geht, habe ich res.sendFile in node.js ausprobiert
– sj
16. April 2021 um 8:06 Uhr
Um diese Lösung zu kritisieren, Sie muss setze den responseType auf „stream“. Andernfalls wird ein Fehler verursacht, wenn Sie versuchen, es an einen anderen Stream weiterzuleiten.
Ich bin nicht wirklich ein Fan der Verwendung von deklarativen Promise-Basisobjekten in JS-Codes, da ich der Meinung bin, dass dies die eigentliche Kernlogik verschmutzt und den Code schwer lesbar macht. Darüber hinaus müssen Sie Ereignishandler und Listener bereitstellen, um sicherzustellen, dass der Code vollständig ist.
Ein saubererer Ansatz auf der gleichen Logik, die die akzeptierte Antwort vorschlägt, ist unten angegeben. Es verwendet die Konzepte von Stream-Pipelines.
Sie können die Codierung auch als Zeichenfolge (anstelle des Optionsobjekts) dekalieren, wenn Sie nur die Codierung und keine anderen Optionen deklarieren. Zeichenfolge wird als Kodierungswert behandelt. als solche:
Während dieser Code die Frage lösen kann, inklusive Erklärung wie und warum dies das Problem löst, würde wirklich dazu beitragen, die Qualität Ihres Beitrags zu verbessern, und wahrscheinlich zu mehr Up-Votes führen. Denken Sie daran, dass Sie die Frage für zukünftige Leser beantworten, nicht nur für die Person, die jetzt fragt. Bitte bearbeiten Sie Ihre Antwort, um Erklärungen hinzuzufügen und einen Hinweis darauf zu geben, welche Einschränkungen und Annahmen gelten.
– Doppel-Piep
27. März 2019 um 11:42 Uhr
@double-beep tnx für deinen Kommentar. Ich habe mit einigen Erklärungen bearbeitet und Material gelesen node fileSystem API über die WriteFile-Funktion. 🙂
– Föderal
27. März 2019 um 11:56 Uhr
Abgabe9527
Ich habe versucht, und ich bin sicher, dass mit response.data.pipe und fs.createWriteStream kann arbeiten.
Außerdem möchte ich meine Situation und Lösung hinzufügen
Lage:
verwenden koa um einen node.js-Server zu entwickeln
verwenden axios um ein pdf über url zu erhalten
verwenden pdf-parse um das pdf zu analysieren
Extrahieren Sie einige Informationen aus PDF und geben Sie sie als JSON an den Browser zurück
Lösung:
const Koa = require('koa');
const app = new Koa();
const axios = require('axios')
const fs = require("fs")
const pdf = require('pdf-parse');
const utils = require('./utils')
app.listen(process.env.PORT || 3000)
app.use(async (ctx, next) => {
let url="https://path/name.pdf"
let resp = await axios({
url: encodeURI(url),
responseType: 'arraybuffer'
})
let data = await pdf(resp.data)
ctx.body = {
phone: utils.getPhone(data.text),
email: utils.getEmail(data.text),
}
})
Bei dieser Lösung muss keine Datei geschrieben und gelesen werden, es ist effizienter.
Während dieser Code die Frage lösen kann, inklusive Erklärung wie und warum dies das Problem löst, würde wirklich dazu beitragen, die Qualität Ihres Beitrags zu verbessern, und wahrscheinlich zu mehr Up-Votes führen. Denken Sie daran, dass Sie die Frage für zukünftige Leser beantworten, nicht nur für die Person, die jetzt fragt. Bitte bearbeiten Sie Ihre Antwort, um Erklärungen hinzuzufügen und einen Hinweis darauf zu geben, welche Einschränkungen und Annahmen gelten.
– Doppel-Piep
27. März 2019 um 11:42 Uhr
@double-beep tnx für deinen Kommentar. Ich habe mit einigen Erklärungen bearbeitet und Material gelesen node fileSystem API über die WriteFile-Funktion. 🙂
Sie erhalten das Konsolenprotokoll “Die Datei wurde gespeichert” und die Datei wird erstellt und nur der Inhalt ist falsch?
– Roland Starke
27. März 2019 um 10:19 Uhr
Wo rufst du axios.get auf? es wird nicht darauf gewartet, dass die Datei geschrieben wird. Versprechen Sie besser die fs oder verwenden Sie fs-extra oder verwenden Sie versprochene Methoden von fs. und verwenden Sie wie return fs.writeFile(…)
– AZ_
27. März 2019 um 10:21 Uhr
@RolandStarke ja, die Datei wird gespeichert
– ar099968
27. März 2019 um 10:27 Uhr
Ich habe unten einen saubereren Ansatz zur Lösung des Problems mit Node-Stream-Pipelines veröffentlicht. Es basiert auf demselben Konzept, das die akzeptierte Antwort vorschlägt. stackoverflow.com/a/64925465/3476378
– Aman Saraf
20. November 2020 um 7:39 Uhr