Ich versuche, ein Skript zum Herunterladen von Bildern mit node.js zu schreiben. Das habe ich bisher:
var maxLength = 10 // 10mb
var download = function(uri, callback) {
http.request(uri)
.on('response', function(res) {
if (res.headers['content-length'] > maxLength*1024*1024) {
callback(new Error('Image too large.'))
} else if (!~[200, 304].indexOf(res.statusCode)) {
callback(new Error('Received an invalid status code.'))
} else if (!res.headers['content-type'].match(/image/)) {
callback(new Error('Not an image.'))
} else {
var body = ''
res.setEncoding('binary')
res
.on('error', function(err) {
callback(err)
})
.on('data', function(chunk) {
body += chunk
})
.on('end', function() {
// What about Windows?!
var path = '/tmp/' + Math.random().toString().split('.').pop()
fs.writeFile(path, body, 'binary', function(err) {
callback(err, path)
})
})
}
})
.on('error', function(err) {
callback(err)
})
.end();
}
Ich möchte dies jedoch robuster machen:
binary
veraltet sein wird. Was mache ich dannWarum: Für eine ähnliche Funktion wie imgur, bei der Benutzer mir eine URL geben können, lade ich das Bild herunter und stelle das Bild in mehreren Größen wieder her.
Ich würde vorschlagen, das Anforderungsmodul zu verwenden. Das Herunterladen einer Datei ist so einfach wie der folgende Code:
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.google.com/images/srpr/logo3w.png', 'google.png', function(){
console.log('done');
});
Ich bin vor einigen Tagen auf dieses Problem gestoßen. Für eine reine NodeJS-Antwort würde ich vorschlagen, Stream zu verwenden, um die Blöcke zusammenzuführen.
var http = require('http'),
Stream = require('stream').Transform,
fs = require('fs');
var url = 'http://www.google.com/images/srpr/logo11w.png';
http.request(url, function(response) {
var data = new Stream();
response.on('data', function(chunk) {
data.Push(chunk);
});
response.on('end', function() {
fs.writeFileSync('image.png', data.read());
});
}).end();
Die neuesten Versionen von Node funktionieren nicht gut mit binären Strings, daher ist das Zusammenführen von Chunks mit Strings keine gute Idee, wenn Sie mit binären Daten arbeiten.
* Seien Sie vorsichtig, wenn Sie 'data.read ()' verwenden, da dies den Stream für den nächsten 'read ()' - Vorgang leeren wird. Wenn Sie es mehrmals verwenden möchten, bewahren Sie es an einem Ort auf.
Sie können Axios (einen Versprechen - basierten HTTP-Client für Node.js) zum Herunterladen verwenden Bilder in der Reihenfolge Ihrer Wahl in einer asynchronen Umgebung :
npm i axios
Anschließend können Sie das folgende grundlegende Beispiel verwenden, um mit dem Herunterladen von Bildern zu beginnen:
const fs = require('fs');
const axios = require('axios');
/* ============================================================
Function: Download Image
============================================================ */
const download_image = (url, image_path) =>
axios({
url,
responseType: 'stream',
}).then(
response =>
new Promise((resolve, reject) => {
response.data
.pipe(fs.createWriteStream(image_path))
.on('finish', () => resolve())
.on('error', e => reject(e));
}),
);
/* ============================================================
Download Images in Order
============================================================ */
(async () => {
let example_image_1 = await download_image('https://example.com/test-1.png', 'example-1.png');
console.log(example_image_1.status); // true
console.log(example_image_1.error); // ''
let example_image_2 = await download_image('https://example.com/does-not-exist.png', 'example-2.png');
console.log(example_image_2.status); // false
console.log(example_image_2.error); // 'Error: Request failed with status code 404'
let example_image_3 = await download_image('https://example.com/test-3.png', 'example-3.png');
console.log(example_image_3.status); // true
console.log(example_image_3.error); // ''
})();
wenn Sie den Fortschritt herunterladen möchten, versuchen Sie Folgendes:
var fs = require('fs');
var request = require('request');
var progress = require('request-progress');
module.exports = function (uri, path, onProgress, onResponse, onError, onEnd) {
progress(request(uri))
.on('progress', onProgress)
.on('response', onResponse)
.on('error', onError)
.on('end', onEnd)
.pipe(fs.createWriteStream(path))
};
wie benutzt man:
var download = require('../lib/download');
download("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png", "~/download/logo.png", function (state) {
console.log("progress", state);
}, function (response) {
console.log("status code", response.statusCode);
}, function (error) {
console.log("error", error);
}, function () {
console.log("done");
});
hinweis: Sie sollten sowohl Anforderungs- als auch Anforderungsfortschrittsmodule installieren, indem Sie Folgendes verwenden:
npm install request request-progress --save
Darauf aufbauend habe ich diese Version verwendet, wenn jemand Fehler in den Schreib-/Lesestreams behandeln muss. Beachten Sie die Funktion stream.read()
im Falle eines Schreibfehler, damit wir den Lesevorgang beenden und close
für den Lesestream auslösen können.
var download = function(uri, filename, callback){
request.head(uri, function(err, res, body){
if (err) callback(err, filename);
else {
var stream = request(uri);
stream.pipe(
fs.createWriteStream(filename)
.on('error', function(err){
callback(error, filename);
stream.read();
})
)
.on('close', function() {
callback(null, filename);
});
}
});
};
var fs = require('fs'),
http = require('http'),
https = require('https');
var Stream = require('stream').Transform;
var downloadImageToUrl = (url, filename, callback) => {
var client = http;
if (url.toString().indexOf("https") === 0){
client = https;
}
client.request(url, function(response) {
var data = new Stream();
response.on('data', function(chunk) {
data.Push(chunk);
});
response.on('end', function() {
fs.writeFileSync(filename, data.read());
});
}).end();
};
downloadImageToUrl('https://www.google.com/images/srpr/logo11w.png', 'public/uploads/users/abc.jpg');
Dies ist eine Erweiterung von Cezarys Antwort. Wenn Sie es in ein bestimmtes Verzeichnis herunterladen möchten, verwenden Sie dieses. Verwenden Sie statt var auch const. So ist es sicher.
const fs = require('fs');
const request = require('request');
var download = function(uri, filename, callback){
request.head(uri, function(err, res, body){
request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);
});
};
download('https://www.google.com/images/srpr/logo3w.png', './images/google.png', function(){
console.log('done');
});