Bagaimana cara mengunduh file dengan Node.js tanpa menggunakan perpustakaan pihak ketiga ?
Saya tidak butuh sesuatu yang istimewa. Saya hanya ingin mengunduh file dari URL yang diberikan, dan kemudian menyimpannya ke direktori yang diberikan.
Bagaimana cara mengunduh file dengan Node.js tanpa menggunakan perpustakaan pihak ketiga ?
Saya tidak butuh sesuatu yang istimewa. Saya hanya ingin mengunduh file dari URL yang diberikan, dan kemudian menyimpannya ke direktori yang diberikan.
Jawaban:
Anda dapat membuat GET
permintaan HTTP dan response
mengirimkannya ke aliran file yang dapat ditulisi:
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);
});
Jika Anda ingin mendukung pengumpulan informasi di baris perintah - seperti menentukan file target atau direktori, atau URL - lihat sesuatu seperti Komandan .
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
telepon; mungkin http://i3.ytimg.com/vi/J---aiyznGQ/mqdefault.jpg
(dan ganti file.png
dengan file.jpg
).
https
Anda harus menggunakan https
selain itu akan menimbulkan kesalahan.
Jangan lupa untuk menangani kesalahan! Kode berikut didasarkan pada jawaban 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()
sendiri pipe
bisa?
Seperti yang dikatakan Michelle Tilley, tetapi dengan aliran kontrol yang sesuai:
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);
});
});
}
Tanpa menunggu finish
acara, skrip naif dapat berakhir dengan file yang tidak lengkap.
Sunting: Terima kasih kepada @Augusto Roman karena menunjukkan yang cb
harus diteruskan file.close
, tidak dipanggil secara eksplisit.
download()
, bagaimana saya melakukannya? Apa yang akan saya tempatkan sebagai cb
argumen? Saya punya download('someURI', '/some/destination', cb)
tetapi tidak mengerti apa yang harus dimasukkan ke dalam cb
Berbicara tentang penanganan kesalahan, lebih baik mendengarkan permintaan kesalahan juga. Saya bahkan akan memvalidasi dengan memeriksa kode respons. Di sini dianggap berhasil hanya untuk 200 kode respons, tetapi kode lain mungkin baik.
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);
});
};
Terlepas dari kesederhanaan relatif dari kode ini, saya akan menyarankan untuk menggunakan modul permintaan karena menangani lebih banyak protokol (halo HTTPS!) Yang tidak didukung secara native oleh http
.
Itu akan dilakukan seperti itu:
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 on finish
tidak akan pernah dipanggil.
Jawaban gfxmonk memiliki ras data yang sangat ketat antara panggilan balik dan file.close()
penyelesaian. file.close()
sebenarnya membutuhkan callback yang dipanggil saat penutupan telah selesai. Jika tidak, penggunaan langsung file mungkin gagal (sangat jarang!).
Solusi lengkap adalah:
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.
});
});
}
Tanpa menunggu acara selesai, skrip naif mungkin berakhir dengan file yang tidak lengkap. Tanpa menjadwalkan cb
panggilan balik melalui penutupan, Anda mungkin mendapatkan perlombaan antara mengakses file dan file yang sebenarnya sudah siap.
var request =
dihapus?
Mungkin node.js telah berubah, tetapi tampaknya ada beberapa masalah dengan solusi lain (menggunakan simpul v8.1.2):
file.close()
di finish
acara tersebut. Per default fs.createWriteStream
disetel ke autoClose: https://nodejs.org/api/fs.html#fs_fs_createwritestream_path_optionsfile.close()
harus dipanggil kesalahan. Mungkin ini tidak diperlukan saat file dihapus ( unlink()
), tetapi biasanya ini: https://nodejs.org/api/stream.html#stream_readable_pipe_destination_optionsstatusCode !== 200
fs.unlink()
tanpa panggilan balik sudah usang (peringatan keluaran)dest
ada file; itu ditimpaDi bawah ini adalah solusi yang dimodifikasi (menggunakan ES6 dan janji-janji) yang menangani masalah ini.
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");
untukconst http = require("http");
Kode berikut didasarkan pada jawaban 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();
});
});
Jangan membuat file saat Anda mendapatkan kesalahan, dan lebih suka menggunakan batas waktu untuk menutup permintaan Anda setelah X detik.
http.get("http://example.com/yourfile.html",function(){})
http.get
. Kebocoran memori hanya jika file terlalu lama untuk diunduh.
bagi mereka yang datang mencari cara berbasis gaya es6 janji, saya kira itu akan menjadi seperti:
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
Bendera disebabkan, untuk beberapa alasan yang saya tidak punya waktu untuk menyelidiki, file saya untuk diunduh tidak lengkap. Tidak ada kesalahan muncul tetapi file .txt yang saya isi memiliki setengah dari baris yang perlu ada di sana. Menghapus logika untuk bendera memperbaikinya. Hanya ingin menunjukkan itu jika seseorang memiliki masalah dengan pendekatan tersebut. Tetap saja, +1
Kode Vince Yuan bagus tetapi tampaknya ada sesuatu yang salah.
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);
});
});
}
Saya lebih suka request () karena Anda bisa menggunakan http dan https.
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));
Hai, saya pikir Anda dapat menggunakan modul child_process dan perintah curl.
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()
Selain itu, ketika Anda ingin mengunduh 、 banyak file besar, Anda dapat menggunakan modul cluster untuk menggunakan lebih banyak core cpu.
Anda dapat menggunakan https://github.com/douzi8/ajax-request#download
request.download('http://res.m.ctrip.com/html5/Content/images/57.png',
function(err, res, body) {}
);
ajax-request
itu bukan perpustakaan pihak ketiga?
Unduh menggunakan janji, yang menyelesaikan aliran yang dapat dibaca. masukkan logika ekstra untuk menangani pengalihan.
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);
}
});
Jika Anda menggunakan metode express use res.download (). jika tidak, gunakan modul fs.
app.get('/read-android', function(req, res) {
var file = "/home/sony/Documents/docs/Android.apk";
res.download(file)
});
(atau)
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");
}
});
}
OJadi jika Anda menggunakan pipa , itu akan menutup semua aliran lainnya dan memastikan bahwa tidak ada kebocoran memori.
Contoh kerja:
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.'); } ); });
Dari jawaban saya untuk "Apa perbedaan antara .pipe dan .pipeline pada stream" .
Path: tipe img: jpg random 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;
}
Tanpa perpustakaan itu bisa buggy hanya untuk menunjukkan. Berikut ini beberapa di antaranya:
Protocol "https:" not supported.
Di sini saran saya:
wget
ataucurl
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');
});
Inilah cara lain untuk menanganinya tanpa ketergantungan pihak ketiga dan juga mencari pengalihan:
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 (yaitu /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')
});
Kita dapat menggunakan modul simpul unduhan dan sangat sederhana, silakan lihat di bawah ini https://www.npmjs.com/package/download
var requestModule=require("request");
requestModule(filePath).pipe(fs.createWriteStream('abc.zip'));