Üçüncü taraf kitaplıkları kullanmadan Node.js ile nasıl dosya indirebilirim ?
Özel bir şeye ihtiyacım yok. Yalnızca belirli bir URL'den dosya indirmek ve daha sonra belirli bir dizine kaydetmek istiyorum.
Üçüncü taraf kitaplıkları kullanmadan Node.js ile nasıl dosya indirebilirim ?
Özel bir şeye ihtiyacım yok. Yalnızca belirli bir URL'den dosya indirmek ve daha sonra belirli bir dizine kaydetmek istiyorum.
Yanıtlar:
Bir HTTP GET
isteği oluşturabilir ve bunu response
yazılabilir bir dosya akışına bağlayabilirsiniz:
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);
});
Komut satırında bir hedef dosya veya dizin veya URL belirtmek gibi bilgi toplamayı desteklemek istiyorsanız, Komutan gibi bir şeye göz atın .
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.get
Hatta farklı bir URL kullanmayı deneyin ; Belki de http://i3.ytimg.com/vi/J---aiyznGQ/mqdefault.jpg
(ve değiştirme file.png
ile file.jpg
).
https
kullanmak gerekir https
o hata atmak olacaktır aksi.
Hataları ele almayı unutmayın! Aşağıdaki kod Augusto Roman'ın cevabına dayanmaktadır.
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()
kendisi pipe
mümkün mü?
Michelle Tilley'in dediği gibi, ancak uygun kontrol akışıyla:
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);
});
});
}
finish
Etkinliği beklemeden saf komut dosyaları eksik bir dosyayla sonuçlanabilir.
Düzenleme: @Augusto Roman'a , açıkça çağrılmaması cb
gereken file.close
, aktarılması gerektiğini işaret ettiği için teşekkürler .
download()
nasıl yaparım? cb
Tartışma olarak neyi yerleştirirdim ? Ben var download('someURI', '/some/destination', cb)
ama cb koymak ne anlamıyorum
Kullanım hatalarından bahsetmişken, hata talep etmek de daha iyi dinleme. Yanıt kodunu kontrol ederek bile doğrularım. Burada sadece 200 yanıt kodu için başarı olarak kabul edilir, ancak diğer kodlar iyi olabilir.
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);
});
};
Bu kodun göreceli sadeliğine rağmen, yerel olarak desteklenmeyen çok daha fazla protokolü (merhaba HTTPS!) İşlediğinden istek modülünü kullanmanızı tavsiye ederim http
.
Bu şu şekilde yapılır:
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 !== 200
cb üzerinde finish
asla çağrılamaz .
gfxmonk'un cevabı, geri arama ve file.close()
tamamlama arasında çok sıkı bir veri yarışına sahiptir . file.close()
aslında kapanma tamamlandığında çağrılan bir geri arama alır. Aksi takdirde, dosyanın hemen kullanımı başarısız olabilir (çok nadiren!).
Tam bir çözüm:
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.
});
});
}
Finish olayını beklemeden saf komut dosyaları eksik bir dosyayla sonuçlanabilir. cb
Geri aramayı yakın plan aracılığıyla zamanlamadan, dosyaya erişme ile dosyaya gerçekten hazır olma arasında bir yarış alabilirsiniz.
var request =
kaldırılırsa global bir değişkenin nasıl oluşturulduğunu nasıl bilirsiniz ?
Belki node.js değişti, ancak diğer çözümlerle ilgili bazı sorunlar var gibi görünüyor (v8.1.2 düğümü kullanılarak):
file.close()
içinde finish
olay. Varsayılan olarak fs.createWriteStream
, autoClose olarak ayarlanır: https://nodejs.org/api/fs.html#fs_fs_createwritestream_path_optionsfile.close()
yanlışlıkla çağrılmalıdır. Dosya silindiğinde ( unlink()
) bu gerekli olmayabilir , ancak normalde: https://nodejs.org/api/stream.html#stream_readable_pipe_destination_optionsstatusCode !== 200
fs.unlink()
geri arama yapılmazsa (çıkış uyarısı)dest
dosya var; geçersiz kılındıAşağıda bu sorunları ele alan değiştirilmiş bir çözüm (ES6 ve vaatler kullanarak) bulunmaktadır.
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");
içinconst http = require("http");
Aşağıdaki kod Brandon Tilley'in cevabına dayanmaktadır:
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();
});
});
Bir hata aldığınızda dosya oluşturmayın ve X saniyeden sonra isteğinizi kapatmak için zaman aşımını kullanmayı tercih edin.
http.get("http://example.com/yourfile.html",function(){})
http.get
. Bellek sızıntısı yalnızca dosyanın indirilmesi çok uzun sürerse.
es6 tarzı vaat tabanlı bir yol arayanlar için, sanırım böyle bir şey olurdu:
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));
responseSet
bayrak, araştırmak için zamanım olmamış bir sebepten dolayı, dosyamın eksik indirilmesine neden oldu. Hiçbir hata attı ama ben dolduruyordu .txt dosya orada olması gereken satırların yarısı vardı. Bayrak mantığını kaldırmak düzeltildi. Sadece birisi yaklaşım ile ilgili sorunları varsa işaret etmek istedim. Hala, +1
Vince Yuan'ın kodu harika ama yanlış bir şey gibi görünüyor.
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);
});
});
}
Ben onunla hem http hem de https kullanabilirsiniz çünkü request () tercih ederim.
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));
Merhaba , Sanırım child_process modülünü ve curl komutunu kullanabilirsiniz.
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()
Ayrıca, large birden fazla dosya indirmek istediğinizde, daha fazla işlemci çekirdeği kullanmak için küme modülünü kullanabilirsiniz.
Https://github.com/douzi8/ajax-request#download kullanabilirsiniz
request.download('http://res.m.ctrip.com/html5/Content/images/57.png',
function(err, res, body) {}
);
ajax-request
üçüncü taraf bir kütüphane değil mi?
Okunabilir bir akışı çözen bir söz kullanarak indirin. yönlendirmeyi işlemek için ekstra mantık ekleyin.
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);
}
});
Ekspres kullanıyorsanız res.download () yöntemini kullanın. aksi takdirde fs modül kullanımı.
app.get('/read-android', function(req, res) {
var file = "/home/sony/Documents/docs/Android.apk";
res.download(file)
});
(veya)
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");
}
});
}
PipBu şekilde boru hattı kullanırsanız , diğer tüm akışları kapatır ve bellek sızıntısı olmadığından emin olur.
Çalışma örneği:
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.'); } ); });
Gönderen cevabım için "akışlarında .pipe ve .pipeline arasındaki fark nedir" .
Yol: img tipi: jpg rastgele 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;
}
Kütüphane olmadan sadece işaret etmek buggy olabilir. Burda biraz var:
Protocol "https:" not supported.
İşte benim önerim:
wget
veyacurl
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');
});
Üçüncü taraf bağımlılığı olmadan ve yönlendirmeleri aramanın başka bir yolu:
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 (yani /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')
});
İndirme düğümü modülünü ve çok basitliğini kullanabiliriz, lütfen https://www.npmjs.com/package/download adresine bakın
var requestModule=require("request");
requestModule(filePath).pipe(fs.createWriteStream('abc.zip'));