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.
Sie können eine HTTP GET
-Anforderung erstellen und ihre response
in einen beschreibbaren Dateistream pipe:
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. Angabe einer Zieldatei oder eines Verzeichnisses oder einer URL, überprüfen Sie etwas wie Commander .
Vergessen Sie nicht, Fehler zu behandeln! 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);
});
};
Wie Brandon Tilley sagte, aber mit der entsprechenden Kontrolle:
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);
});
});
}
Ohne auf das finish
-Ereignis zu warten, erhalten naive Skripts möglicherweise eine unvollständige Datei.
Edit: Danke an @Augusto Roman für den Hinweis, dass cb
an file.close
übergeben werden soll, nicht explizit aufgerufen wird.
Apropos Umgang mit Fehlern, es ist noch besser, Fehler zu hören. Ich würde es sogar überprüfen, indem ich den Antwortcode überprüfe. Hier gilt der Erfolg nur für 200 Antwortcodes, andere Codes sind jedoch möglicherweise gut.
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 Modul request zu verwenden , da es viele weitere Protokolle verarbeitet (Hallo HTTPS!), Die von http
nicht nativ unterstützt werden.
Das wäre so gemacht:
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);
});
};
die Antwort von gfxmonk hat einen sehr engen Datenwettlauf zwischen dem Rückruf und dem Abschluss der file.close()
. file.close()
nimmt tatsächlich einen Rückruf an, der aufgerufen wird, wenn das Schließen abgeschlossen ist. Andernfalls kann die sofortige Verwendung der Datei fehlschlagen (sehr selten!).
Eine Komplettlö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 Beendigungsereignis zu warten, erhalten naive Skripte möglicherweise eine unvollständige Datei. Ohne den cb
-Callback über close zu terminieren, kann es vorkommen, dass zwischen dem Zugriff auf die Datei und der tatsächlich bereitstehenden Datei ein Wettlauf stattfindet.
Vielleicht hat node.js sich geändert, aber es scheint, dass es Probleme mit den anderen Lösungen gibt (mit dem Knoten v8.1.2):
file.close()
nicht im Ereignis finish
aufrufen. Standardmäßig ist fs.createWriteStream
auf autoClose gesetzt: https://nodejs.org/api/fs.html#fs_fs_createwritestream_path_optionsfile.close()
sollte bei einem Fehler aufgerufen werden. Möglicherweise ist dies nicht erforderlich, wenn die Datei gelöscht wird (unlink()
), normalerweise jedoch: https://nodejs.org/api/stream.html#stream_readable_pipe_destination_optionsstatusCode !== 200
nicht gelöschtfs.unlink()
ohne Rückruf ist veraltet (gibt Warnung aus)dest
Datei vorhanden ist; es wird außer Kraft gesetztNachfolgend finden Sie eine modifizierte Lösung (mit ES6 und Versprechungen), die diese Probleme löst.
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);
}
});
});
}
für diejenigen, die auf der Suche nach einem auf Es6 basierenden Versprechen waren, denke ich, wäre dies etwa so:
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));
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 ziehen Sie es vor, nach x Sekunden die Anforderung mit timeout zu schließen.
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));
Vince Yuans Code ist großartig, scheint aber 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);
});
});
}
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) {}
);
Wenn Sie Express verwenden, verwenden Sie die Methode res.download (). ansonsten 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");
}
});
}
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;
}
Download mit Versprechen, das einen lesbaren Stream auflöst. Legen Sie zusätzliche Logik für die Weiterleitung bereit.
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);
}
});
Hallo, ich denke, Sie können das child_process -Modul und den curl-Befehl 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()
Außerdem können Sie, wenn Sie große, mehrere Dateien herunterladen möchten, das Modul cluster verwenden, um weitere CPU-Kerne zu verwenden.
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);
});
};
Sie können versuchen, res.redirect
für die Download-URL der https-Datei zu verwenden. Anschließend wird die Datei heruntergeladen.
Wie: res.redirect('https//static.file.com/file.txt');
Ohne Bibliothek könnte es fehlerhaft sein, nur um darauf hinzuweisen. Hier sind ein paar:
Protocol "https:" not supported.
Hier mein Vorschlag:
wget
oder curl
aufrufenvar wget = require('node-wget-promise'); wget('http://nodejs.org/images/logo.svg');
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');
});