Wie lade ich eine Datei mit Node.js herunter, ohne Bibliotheken von Drittanbietern zu verwenden ?
Ich brauche nichts Besonderes. Ich möchte nur eine Datei von einer bestimmten URL herunterladen und sie dann in einem bestimmten Verzeichnis speichern.
Wie lade ich eine Datei mit Node.js herunter, ohne Bibliotheken von Drittanbietern zu verwenden ?
Ich brauche nichts Besonderes. Ich möchte nur eine Datei von einer bestimmten URL herunterladen und sie dann in einem bestimmten Verzeichnis speichern.
Antworten:
Sie können eine HTTP- GETAnforderung erstellen und responsein einen beschreibbaren Dateistream weiterleiten:
const http = require('http');
const fs = require('fs');
const file = fs.createWriteStream("file.jpg");
const request = http.get("http://i3.ytimg.com/vi/J---aiyznGQ/mqdefault.jpg", function(response) {
response.pipe(file);
});
Wenn Sie das Sammeln von Informationen in der Befehlszeile unterstützen möchten, z. B. das Angeben einer Zieldatei, eines Zieldverzeichnisses oder einer URL, lesen Sie etwas wie Commander .
node.js:201 throw e; // process.nextTick error, or 'error' event on first tick ^ Error: connect ECONNREFUSED at errnoException (net.js:646:11) at Object.afterConnect [as oncomplete] (net.js:637:18) .
http.getZeile zu verwenden. vielleicht http://i3.ytimg.com/vi/J---aiyznGQ/mqdefault.jpg(und ersetzen file.pngdurch file.jpg).
httpsmüssen, httpsandernfalls wird ein Fehler ausgegeben.
Vergessen Sie nicht, mit Fehlern umzugehen! Der folgende Code basiert auf der Antwort von Augusto Roman.
var http = require('http');
var fs = require('fs');
var download = function(url, dest, cb) {
var file = fs.createWriteStream(dest);
var request = http.get(url, function(response) {
response.pipe(file);
file.on('finish', function() {
file.close(cb); // close() is async, call cb after close completes.
});
}).on('error', function(err) { // Handle errors
fs.unlink(dest); // Delete the file async. (But we don't check the result)
if (cb) cb(err.message);
});
};
download()selbst in der pipeLage?
Wie Michelle Tilley sagte, aber mit dem entsprechenden Kontrollfluss:
var http = require('http');
var fs = require('fs');
var download = function(url, dest, cb) {
var file = fs.createWriteStream(dest);
http.get(url, function(response) {
response.pipe(file);
file.on('finish', function() {
file.close(cb);
});
});
}
Ohne auf das finishEreignis zu warten , können naive Skripte eine unvollständige Datei enthalten.
Bearbeiten: Vielen Dank an @Augusto Roman für den Hinweis, dass an übergeben werden cbsollte file.close, nicht explizit aufgerufen.
download(), wie würde ich das tun? Was würde ich als cbArgument angeben? Ich habe die download('someURI', '/some/destination', cb)aber nicht verstanden, was ich in die cb setzen soll
Apropos Fehlerbehandlung: Es ist sogar noch besser, Anforderungsfehler zu hören. Ich würde sogar validieren, indem ich den Antwortcode überprüfe. Hier wird es nur für 200 Antwortcodes als Erfolg angesehen, aber andere Codes könnten gut sein.
const fs = require('fs');
const http = require('http');
const download = (url, dest, cb) => {
const file = fs.createWriteStream(dest);
const request = http.get(url, (response) => {
// check if response is success
if (response.statusCode !== 200) {
return cb('Response status was ' + response.statusCode);
}
response.pipe(file);
});
// close() is async, call cb after close completes
file.on('finish', () => file.close(cb));
// check for request error too
request.on('error', (err) => {
fs.unlink(dest);
return cb(err.message);
});
file.on('error', (err) => { // Handle errors
fs.unlink(dest); // Delete the file async. (But we don't check the result)
return cb(err.message);
});
};
Trotz der relativen Einfachheit dieses Codes würde ich empfehlen, das Anforderungsmodul zu verwenden, da es viel mehr Protokolle (Hallo HTTPS!) Verarbeitet, die von Haus aus nicht unterstützt werden http.
Das würde so gemacht werden:
const fs = require('fs');
const request = require('request');
const download = (url, dest, cb) => {
const file = fs.createWriteStream(dest);
const sendReq = request.get(url);
// verify response code
sendReq.on('response', (response) => {
if (response.statusCode !== 200) {
return cb('Response status was ' + response.statusCode);
}
sendReq.pipe(file);
});
// close() is async, call cb after close completes
file.on('finish', () => file.close(cb));
// check for request errors
sendReq.on('error', (err) => {
fs.unlink(dest);
return cb(err.message);
});
file.on('error', (err) => { // Handle errors
fs.unlink(dest); // Delete the file async. (But we don't check the result)
return cb(err.message);
});
};
response.statusCode !== 200das cb on finishniemals aufgerufen wird.
Die Antwort von gfxmonk hat ein sehr enges Datenrennen zwischen dem Rückruf und dem file.close()Abschluss. file.close()Nimmt tatsächlich einen Rückruf entgegen, der aufgerufen wird, wenn der Abschluss abgeschlossen ist. Andernfalls kann die sofortige Verwendung der Datei fehlschlagen (sehr selten!).
Eine vollständige Lösung ist:
var http = require('http');
var fs = require('fs');
var download = function(url, dest, cb) {
var file = fs.createWriteStream(dest);
var request = http.get(url, function(response) {
response.pipe(file);
file.on('finish', function() {
file.close(cb); // close() is async, call cb after close completes.
});
});
}
Ohne auf das Endereignis zu warten, können naive Skripte eine unvollständige Datei enthalten. Ohne den cbRückruf über das Schließen zu planen , kann es zu einem Wettlauf zwischen dem Zugriff auf die Datei und der tatsächlichen Bereitschaft der Datei kommen.
var request =entfernt wird?
Möglicherweise hat sich node.js geändert, aber es scheint, dass es einige Probleme mit den anderen Lösungen gibt (unter Verwendung von Node v8.1.2):
file.close()die finishVeranstaltung nicht anrufen . Standardmäßig fs.createWriteStreamist der Wert auf autoClose eingestellt: https://nodejs.org/api/fs.html#fs_fs_createwritestream_path_optionsfile.close()sollte bei Fehler aufgerufen werden. Möglicherweise wird dies nicht benötigt, wenn die Datei gelöscht wird ( unlink()), aber normalerweise ist dies: https://nodejs.org/api/stream.html#stream_readable_pipe_destination_optionsstatusCode !== 200fs.unlink() ohne Rückruf ist veraltet (Ausgabe Warnung)destDatei vorhanden ist; es wird überschriebenIm Folgenden finden Sie eine modifizierte Lösung (mit ES6 und Versprechungen), mit der diese Probleme behoben werden können.
const http = require("http");
const fs = require("fs");
function download(url, dest) {
return new Promise((resolve, reject) => {
const file = fs.createWriteStream(dest, { flags: "wx" });
const request = http.get(url, response => {
if (response.statusCode === 200) {
response.pipe(file);
} else {
file.close();
fs.unlink(dest, () => {}); // Delete temp file
reject(`Server responded with ${response.statusCode}: ${response.statusMessage}`);
}
});
request.on("error", err => {
file.close();
fs.unlink(dest, () => {}); // Delete temp file
reject(err.message);
});
file.on("finish", () => {
resolve();
});
file.on("error", err => {
file.close();
if (err.code === "EEXIST") {
reject("File already exists");
} else {
fs.unlink(dest, () => {}); // Delete temp file
reject(err.message);
}
});
});
}
const https = require("https");fürconst http = require("http");
Der folgende Code basiert auf der Antwort von Brandon Tilley:
var http = require('http'),
fs = require('fs');
var request = http.get("http://example12345.com/yourfile.html", function(response) {
if (response.statusCode === 200) {
var file = fs.createWriteStream("copy.html");
response.pipe(file);
}
// Add timeout.
request.setTimeout(12000, function () {
request.abort();
});
});
Erstellen Sie keine Datei, wenn Sie eine Fehlermeldung erhalten, und verwenden Sie lieber das Zeitlimit, um Ihre Anforderung nach X Sekunden zu schließen.
http.get("http://example.com/yourfile.html",function(){})
http.get. Der Speicherverlust tritt nur auf, wenn das Herunterladen der Datei zu lange dauert.
Für diejenigen, die auf der Suche nach einem Versprechen im Es6-Stil waren, wäre es wahrscheinlich so etwas wie:
var http = require('http');
var fs = require('fs');
function pDownload(url, dest){
var file = fs.createWriteStream(dest);
return new Promise((resolve, reject) => {
var responseSent = false; // flag to make sure that response is sent only once.
http.get(url, response => {
response.pipe(file);
file.on('finish', () =>{
file.close(() => {
if(responseSent) return;
responseSent = true;
resolve();
});
});
}).on('error', err => {
if(responseSent) return;
responseSent = true;
reject(err);
});
});
}
//example
pDownload(url, fileLocation)
.then( ()=> console.log('downloaded file no issues...'))
.catch( e => console.error('error while downloading', e));
responseSetflag verursachte aus irgendeinem Grund, für den ich keine Zeit gehabt hatte, meine Datei unvollständig herunterzuladen. Es sind keine Fehler aufgetreten, aber die von mir aufgefüllte TXT-Datei enthielt die Hälfte der Zeilen, die vorhanden sein mussten. Durch Entfernen der Logik für das Flag wurde das Problem behoben. Ich wollte nur darauf hinweisen, wenn jemand Probleme mit dem Ansatz hatte. Noch +1
Der Code von Vince Yuan ist großartig, aber es scheint etwas falsch zu sein.
function download(url, dest, callback) {
var file = fs.createWriteStream(dest);
var request = http.get(url, function (response) {
response.pipe(file);
file.on('finish', function () {
file.close(callback); // close() is async, call callback after close completes.
});
file.on('error', function (err) {
fs.unlink(dest); // Delete the file async. (But we don't check the result)
if (callback)
callback(err.message);
});
});
}
Ich bevorzuge request (), da Sie damit sowohl http als auch https verwenden können.
request('http://i3.ytimg.com/vi/J---aiyznGQ/mqdefault.jpg')
.pipe(fs.createWriteStream('cat.jpg'))
"As of Feb 11th 2020, request is fully deprecated. No new changes are expected to land. In fact, none have landed for some time."
const download = (url, path) => new Promise((resolve, reject) => {
http.get(url, response => {
const statusCode = response.statusCode;
if (statusCode !== 200) {
return reject('Download error!');
}
const writeStream = fs.createWriteStream(path);
response.pipe(writeStream);
writeStream.on('error', () => reject('Error writing to file!'));
writeStream.on('finish', () => writeStream.close(resolve));
});}).catch(err => console.error(err));
Hallo , Ich denke, Sie können das Modul child_process und den Befehl curl verwenden.
const cp = require('child_process');
let download = async function(uri, filename){
let command = `curl -o ${filename} '${uri}'`;
let result = cp.execSync(command);
};
async function test() {
await download('http://zhangwenning.top/20181221001417.png', './20181221001417.png')
}
test()
Wenn Sie große Dateien herunterladen möchten, können Sie außerdem das Cluster- Modul verwenden, um mehr CPU-Kerne zu verwenden.
Sie können https://github.com/douzi8/ajax-request#download verwenden
request.download('http://res.m.ctrip.com/html5/Content/images/57.png',
function(err, res, body) {}
);
ajax-requestes sich nicht um eine Drittanbieter-Bibliothek handelt?
Download mit Versprechen, die einen lesbaren Stream auflösen. Setzen Sie zusätzliche Logik ein, um die Umleitung zu handhaben.
var http = require('http');
var promise = require('bluebird');
var url = require('url');
var fs = require('fs');
var assert = require('assert');
function download(option) {
assert(option);
if (typeof option == 'string') {
option = url.parse(option);
}
return new promise(function(resolve, reject) {
var req = http.request(option, function(res) {
if (res.statusCode == 200) {
resolve(res);
} else {
if (res.statusCode === 301 && res.headers.location) {
resolve(download(res.headers.location));
} else {
reject(res.statusCode);
}
}
})
.on('error', function(e) {
reject(e);
})
.end();
});
}
download('http://localhost:8080/redirect')
.then(function(stream) {
try {
var writeStream = fs.createWriteStream('holyhigh.jpg');
stream.pipe(writeStream);
} catch(e) {
console.error(e);
}
});
Wenn Sie Express verwenden, verwenden Sie die Methode res.download (). sonst fs Modul verwenden.
app.get('/read-android', function(req, res) {
var file = "/home/sony/Documents/docs/Android.apk";
res.download(file)
});
(oder)
function readApp(req,res) {
var file = req.fileName,
filePath = "/home/sony/Documents/docs/";
fs.exists(filePath, function(exists){
if (exists) {
res.writeHead(200, {
"Content-Type": "application/octet-stream",
"Content-Disposition" : "attachment; filename=" + file});
fs.createReadStream(filePath + file).pipe(res);
} else {
res.writeHead(400, {"Content-Type": "text/plain"});
res.end("ERROR File does NOT Exists.ipa");
}
});
}
✅Wenn Sie eine Pipeline verwenden , werden alle anderen Streams geschlossen und es wird sichergestellt, dass keine Speicherlecks auftreten.
Arbeitsbeispiel:
const http = require('http'); const { pipeline } = require('stream'); const fs = require('fs'); const file = fs.createWriteStream('./file.jpg'); http.get('http://via.placeholder.com/150/92c952', response => { pipeline( response, file, err => { if (err) console.error('Pipeline failed.', err); else console.log('Pipeline succeeded.'); } ); });
Von meiner Antwort auf "Was ist der Unterschied zwischen .pipe und .pipeline in Streams" .
Pfad: img Typ: jpg zufällige Uniqid
function resim(url) {
var http = require("http");
var fs = require("fs");
var sayi = Math.floor(Math.random()*10000000000);
var uzanti = ".jpg";
var file = fs.createWriteStream("img/"+sayi+uzanti);
var request = http.get(url, function(response) {
response.pipe(file);
});
return sayi+uzanti;
}
Ohne Bibliothek könnte es fehlerhaft sein, nur um darauf hinzuweisen. Hier sind ein paar:
Protocol "https:" not supported.Hier mein Vorschlag:
wget oder aufcurl
var wget = require('node-wget-promise');
wget('http://nodejs.org/images/logo.svg');
function download(url, dest, cb) {
var request = http.get(url, function (response) {
const settings = {
flags: 'w',
encoding: 'utf8',
fd: null,
mode: 0o666,
autoClose: true
};
// response.pipe(fs.createWriteStream(dest, settings));
var file = fs.createWriteStream(dest, settings);
response.pipe(file);
file.on('finish', function () {
let okMsg = {
text: `File downloaded successfully`
}
cb(okMsg);
file.end();
});
}).on('error', function (err) { // Handle errors
fs.unlink(dest); // Delete the file async. (But we don't check the result)
let errorMsg = {
text: `Error in file downloadin: ${err.message}`
}
if (cb) cb(errorMsg);
});
};
var fs = require('fs'),
request = require('request');
var download = function(uri, filename, callback){
request.head(uri, function(err, res, body){
console.log('content-type:', res.headers['content-type']);
console.log('content-length:', res.headers['content-length']);
request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);
});
};
download('https://www.cryptocompare.com/media/19684/doge.png', 'icons/taskks12.png', function(){
console.log('done');
});
Hier ist noch eine andere Möglichkeit, ohne Abhängigkeit von Drittanbietern damit umzugehen und auch nach Weiterleitungen zu suchen:
var download = function(url, dest, cb) {
var file = fs.createWriteStream(dest);
https.get(url, function(response) {
if ([301,302].indexOf(response.statusCode) !== -1) {
body = [];
download(response.headers.location, dest, cb);
}
response.pipe(file);
file.on('finish', function() {
file.close(cb); // close() is async, call cb after close completes.
});
});
}
download.js (dh /project/utils/download.js)
const fs = require('fs');
const request = require('request');
const download = (uri, filename, callback) => {
request.head(uri, (err, res, body) => {
console.log('content-type:', res.headers['content-type']);
console.log('content-length:', res.headers['content-length']);
request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);
});
};
module.exports = { download };
app.js.
...
// part of imports
const { download } = require('./utils/download');
...
// add this function wherever
download('https://imageurl.com', 'imagename.jpg', () => {
console.log('done')
});
Wir können das Download-Knoten-Modul verwenden und es ist sehr einfach. Weitere Informationen finden Sie unter https://www.npmjs.com/package/download
var requestModule=require("request");
requestModule(filePath).pipe(fs.createWriteStream('abc.zip'));