Bagaimana cara men-download sebuah file dengan Node.js tanpa menggunakan pustaka pihak ketiga?
Saya don't perlu sesuatu yang istimewa. Saya hanya ingin men-download file dari URL yang diberikan, dan kemudian menyimpannya ke direktori tertentu.
Anda dapat membuat sebuah HTTP MENDAPATKAN
permintaan dan pipa yang respon
menjadi writable file stream:
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 pada baris perintah--seperti menentukan target file atau direktori, atau URL-memeriksa sesuatu seperti Komandan.
Don't lupa untuk menangani kesalahan! Kode berikut ini didasarkan pada Augusto Roman's jawaban.
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);
});
};
Sebagai Michelle Tilley kata, tetapi dengan kontrol yang tepat flow:
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);
});
});
}
Tanpa menunggu `selesai acara, naif script mungkin berakhir dengan lengkap file.
Edit: Terima kasih untuk @Augusto Romawi untuk menunjukkan bahwa cb
harus dilalui untuk file.dekat
, tidak disebut secara eksplisit.
Berbicara tentang penanganan kesalahan,'s bahkan lebih baik mendengarkan permintaan kesalahan juga. I'd bahkan memvalidasi dengan memeriksa kode respon. Berikut ini's dianggap sukses hanya untuk 200 kode respon, tapi kode-kode lain yang mungkin lebih 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);
});
};
Meskipun relatif sederhana dari kode ini, saya akan menyarankan untuk menggunakan request modul saat ini menangani lebih banyak protokol (halo HTTPS!) yang tidak't native didukung oleh http
.
Yang akan dilakukan seperti:
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);
});
};
gfxmonk's jawaban yang sangat ketat data perlombaan antara callback dan file.close()
menyelesaikan. file.close()
benar-benar membutuhkan callback yang disebut ketika dekat telah melengkapi verifikasi identitas. Jika tidak, langsung menggunakan 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 selesai acara, naif script mungkin berakhir dengan lengkap file. Tanpa penjadwalan cb
panggilan balik melalui dekat, anda mungkin mendapatkan perlombaan antara mengakses file dan file benar-benar siap.
Mungkin node.js telah berubah, tapi tampaknya ada beberapa masalah dengan solusi lain (menggunakan node v8.1.2):
file.close()
dalam finish
acara. Per default fs.createWriteStream
diatur untuk autoClose: https://nodejs.org/api/fs.html#fs_fs_createwritestream_path_optionsfile.close()
harus disebut pada kesalahan. Mungkin ini tidak dibutuhkan ketika file dihapus (unlink()
), tetapi biasanya itu adalah: https://nodejs.org/api/stream.html#stream_readable_pipe_destination_optionsstatus !== 200
fs.unlink()
tanpa callback adalah usang (output peringatan)tujuan
file yang ada; hal ini ditimpaDi bawah ini adalah modifikasi solusi (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);
}
});
});
}
Kode berikut ini didasarkan pada Brandon Tilley's jawaban :
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();
});
});
Don't membuat file ketika anda mendapatkan pesan kesalahan, dan lebih menyukai untuk menggunakan timeout untuk menutup permintaan anda setelah X detik.
untuk orang-orang yang datang mencari es6-gaya janji berdasarkan cara, saya kira itu akan menjadi sesuatu 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));
Vince Yuan's kode adalah besar, tetapi tampaknya menjadi 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);
});
});
}
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));
Hi, saya pikir anda dapat menggunakan child_process modul dan perintah curl. `` const cp = require('child_process');
biarkan download = async function(uri, filename){
mari perintah = curl -o ${nama file} '${url}'
;
biarkan hasil = cp.execSync(perintah);
};
async function test() { menanti download('http://zhangwenning.top/20181221001417.png', './20181221001417.png') }
test() `` Selain itu, ketika anda ingin men-download besar, beberapa file, anda dapat menggunakan cluster modul untuk menggunakan lebih banyak core cpu.
Jika anda menggunakan express menggunakan res.download() metode. jika fs penggunaan modul.
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");
}
});
}
Download menggunakan janji, yang menyelesaikan dibaca streaming. menempatkan tambahan logika untuk menangani mengarahkan.
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);
}
});
Path : img jenis : 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;
}
Berikut ini's cara lain untuk mengatasinya tanpa pihak ke-3 ketergantungan dan juga mencari pengalihan:
`` var download = function(url, dest, cb) { var file = fs.createWriteStream(dest); https.get(url, function(response) { if ([301,302].indexOf(respon.statusCode) !== -1) { tubuh = []; download(respon.header.lokasi, dest, cb); } respon.pipa(file); file.pada('selesai', function() { file.dekat(cb); // close() adalah async, panggilan cb setelah hampir selesai. }); }); }
Tanpa perpustakaan ini bisa menjadi kereta hanya untuk menunjukkan. Berikut ini adalah beberapa:
Protokol "https:" tidak didukung.
Berikut ini saran saya:
wget
atau keriting
var wget = require('node-wget-janji'); 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);
});
};