타사 라이브러리를 사용하지 않고 Node.js로 파일을 어떻게 다운로드 합니까?
나는 특별한 것이 필요하지 않습니다. 주어진 URL에서 파일을 다운로드 한 다음 주어진 디렉토리에 저장하고 싶습니다.
타사 라이브러리를 사용하지 않고 Node.js로 파일을 어떻게 다운로드 합니까?
나는 특별한 것이 필요하지 않습니다. 주어진 URL에서 파일을 다운로드 한 다음 주어진 디렉토리에 저장하고 싶습니다.
답변:
HTTP GET
요청을 작성하여 response
쓰기 가능한 파일 스트림으로 파이프 할 수 있습니다 .
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);
});
대상 파일이나 디렉토리 또는 URL 지정과 같이 명령 행에서 정보 수집을 지원하려면 Commander 와 같은 것을 확인하십시오 .
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
회선 에 다른 URL을 사용해보십시오 . 어쩌면 http://i3.ytimg.com/vi/J---aiyznGQ/mqdefault.jpg
(및 교체 file.png
와 함께 file.jpg
).
https
사용합니다 https
이 오류가 발생합니다 그렇지.
오류를 처리하는 것을 잊지 마십시오! 다음 코드는 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()
자체가 pipe
가능합니까?
Michelle Tilley가 말했듯이 적절한 제어 흐름이 있습니다.
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
이벤트를 기다리지 않고 순진 스크립트는 불완전한 파일로 끝날 수 있습니다.
편집 : @Augusto Roman에게 명시 적으로 호출되지 않고에 cb
전달해야한다고 지적 해 주셔서 감사합니다 file.close
.
download()
하면 어떻게해야합니까? 나는 cb
논쟁 으로 무엇을 놓을 것인가? 나는 가지고 download('someURI', '/some/destination', cb)
있지만 cb에 넣을 것을 이해하지 못한다
오류 처리와 관련하여 오류를 요청하는 것이 더 좋습니다. 응답 코드를 확인하여 유효성을 검사합니다. 여기서는 200 응답 코드에 대해서만 성공한 것으로 간주되지만 다른 코드는 좋습니다.
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);
});
};
이 코드의 상대적 단순성에도 불구하고 요청 모듈 을 기본적으로 지원하지 않는 더 많은 프로토콜 (hello HTTPS!)을 처리 하므로 요청 모듈 을 사용하는 것이 http
좋습니다.
그렇게 할 것입니다 :
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
이 호출되지 않으면
gfxmonk의 답변은 콜백과 file.close()
완료 사이의 데이터 경쟁이 매우 엄격합니다 . file.close()
실제로 닫기가 완료되면 호출되는 콜백을받습니다. 그렇지 않으면 파일을 즉시 사용하지 못할 수 있습니다 (매우 드물게!).
완전한 해결책은 다음과 같습니다.
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.
});
});
}
종료 이벤트를 기다리지 않고 순진 스크립트는 불완전한 파일로 끝날 수 있습니다. cb
닫기를 통해 콜백을 예약하지 않으면 파일에 액세스하는 것과 실제로 준비중인 파일간에 경쟁이 발생할 수 있습니다.
var request =
가 제거되면 어떻게 생성되는지 어떻게 알 수 있습니까?
아마 node.js가 변경되었지만 다른 솔루션에 문제가있는 것 같습니다 (노드 v8.1.2 사용) :
file.close()
에서 finish
이벤트입니다. 기본적 fs.createWriteStream
으로이 값은 autoClose로 설정되어 있습니다 : https://nodejs.org/api/fs.html#fs_fs_createwritestream_path_optionsfile.close()
오류가 발생하면 호출해야합니다. 파일을 삭제할 때 필요하지 않을 수도 unlink()
있지만 ( ) 일반적으로 다음과 같습니다. https://nodejs.org/api/stream.html#stream_readable_pipe_destination_optionsstatusCode !== 200
fs.unlink()
콜백이 없으면 더 이상 사용되지 않습니다 (출력 경고)dest
파일이 존재 하면 ; 재정의되었습니다다음은 이러한 문제를 해결하는 수정 된 솔루션 (ES6 및 약속 사용)입니다.
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");
를 위해const http = require("http");
다음 코드는 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();
});
});
오류가 발생했을 때 파일을 만들지 말고 X 초 후에 시간 초과를 사용하여 요청을 닫는 것을 선호합니다.
http.get("http://example.com/yourfile.html",function(){})
http.get
. 파일을 다운로드하는 데 시간이 너무 오래 걸리는 경우에만 메모리 누수가 발생합니다.
es6 스타일의 약속 기반 방식을 찾은 사람들에게는 다음과 같은 것 같습니다.
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
플래그로 인해 조사 할 시간이 없었기 때문에 파일이 불완전하게 다운로드되었습니다. 오류가 발생하지 않았지만 내가 채우는 .txt 파일에는 절반의 행이 있어야했습니다. 플래그의 논리를 제거하면 문제가 해결되었습니다. 누군가 접근 방식에 문제가 있다면 지적하고 싶었습니다. 여전히 +1
빈스 위안의 코드는 훌륭하지만 뭔가 잘못된 것 같습니다.
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);
});
});
}
http와 https를 모두 사용할 수 있기 때문에 request ()를 선호합니다.
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));
안녕하세요, child_process 모듈과 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()
또한, 여러 개의 대용량 파일을 다운로드하려는 경우 클러스터 모듈을 사용하여 더 많은 CPU 코어를 사용할 수 있습니다 .
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
타사 라이브러리가 아니라고 생각하십니까 ?
읽을 수있는 스트림을 해결하는 약속을 사용하여 다운로드하십시오. 리디렉션을 처리하기 위해 추가 논리를 넣습니다.
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);
}
});
express를 사용하는 경우 res.download () 메소드를 사용하십시오. 그렇지 않으면 fs 모듈 사용.
app.get('/read-android', function(req, res) {
var file = "/home/sony/Documents/docs/Android.apk";
res.download(file)
});
(또는)
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");
}
});
}
pipeline 따라서 pipeline 을 사용하면 다른 모든 스트림을 닫고 메모리 누수가 없는지 확인합니다.
작업 예 :
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.'); } ); });
경로 : 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;
}
라이브러리가 없으면 지적하기가 까다로울 수 있습니다. 몇 가지가 있습니다 :
Protocol "https:" not supported.
여기 내 제안 :
wget
또는 같은 시스템 도구를 호출curl
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');
});
타사 종속성없이 처리하고 리디렉션을 검색하는 또 다른 방법이 있습니다.
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 (예 : /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')
});
우리는 다운로드 노드 모듈을 사용할 수 있으며 매우 간단합니다. 아래를 참조하십시오 https://www.npmjs.com/package/download
var requestModule=require("request");
requestModule(filePath).pipe(fs.createWriteStream('abc.zip'));