[英]How to download a file with Node.js (without using third-party libraries)?
How do I download a file with Node.js without using third-party libraries ?如何在不使用第三方库的情况下下载带有 Node.js 的文件?
I don't need anything special.我不需要什么特别的。 I only want to download a file from a given URL, and then save it to a given directory.
我只想从给定的 URL 下载文件,然后将其保存到给定目录。
You can create an HTTP GET
request and pipe its response
into a writable file stream:您可以创建 HTTP
GET
请求并将其response
通过管道传输到可写文件流中:
const http = require('http'); // or 'https' for https:// URLs
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);
// after download completed close filestream
file.on("finish", () => {
file.close();
console.log("Download Completed");
});
});
If you want to support gathering information on the command line--like specifying a target file or directory, or URL--check out something like Commander .如果您想支持在命令行上收集信息——比如指定目标文件或目录,或 URL——请查看Commander之类的内容。
More detailed explanation in https://sebhastian.com/nodejs-download-file/更详细的解释在https://sebhastian.com/nodejs-download-file/
Don't forget to handle errors!不要忘记处理错误! The following code is based on Augusto Roman's answer.
以下代码基于 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);
});
};
As Michelle Tilley said, but with the appropriate control flow:正如 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);
});
});
}
Without waiting for the finish
event, naive scripts may end up with an incomplete file.如果不等待
finish
事件,天真的脚本可能会以不完整的文件结束。
Edit: Thanks to @Augusto Roman for pointing out that cb
should be passed to file.close
, not called explicitly.编辑:感谢@Augusto Roman 指出
cb
应该传递给file.close
,而不是显式调用。
Speaking of handling errors, it's even better listening to request errors too.说到处理错误,听请求错误也更好。 I'd even validate by checking response code.
我什至会通过检查响应代码来验证。 Here it's considered success only for 200 response code, but other codes might be good.
此处仅对 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, () => cb(err.message)); // delete the (partial) file and then return the error
});
file.on('error', (err) => { // Handle errors
fs.unlink(dest, () => cb(err.message)); // delete the (partial) file and then return the error
});
};
Despite the relative simplicity of this code, I would advise to use the request module as it handles many more protocols (hello HTTPS!) which aren't natively supported by http
.尽管这段代码相对简单,但我还是建议使用request 模块,因为它可以处理更多
http
本身不支持的协议(你好 HTTPS!)。
That would be done like so:可以这样做:
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, () => cb(err.message)); // delete the (partial) file and then return the error
});
file.on('error', (err) => { // Handle errors
fs.unlink(dest, () => cb(err.message)); // delete the (partial) file and then return the error
});
};
EDIT :编辑:
To make it work with https
, change要使其与
https
一起使用,请更改
const http = require('http');
to至
const http = require('https');
gfxmonk's answer has a very tight data race between the callback and the file.close()
completing. gfxmonk 的答案在回调和
file.close()
完成之间存在非常紧张的数据竞争。 file.close()
actually takes a callback that is called when the close has completed. file.close()
实际上接受一个在关闭完成时调用的回调。 Otherwise, immediate uses of the file may fail (very rarely!).否则,文件的立即使用可能会失败(非常罕见!)。
A complete solution is:一个完整的解决方案是:
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.
});
});
}
Without waiting for the finish event, naive scripts may end up with an incomplete file.如果不等待完成事件,天真的脚本可能会以不完整的文件结束。 Without scheduling the
cb
callback via close, you may get a race between accessing the file and the file actually being ready.如果不通过 close 安排
cb
回调,您可能会在访问文件和实际准备好的文件之间发生竞争。
Maybe node.js has changed, but it seems there are some problems with the other solutions (using node v8.1.2):也许 node.js 发生了变化,但其他解决方案似乎存在一些问题(使用 node v8.1.2):
file.close()
in the finish
event.finish
事件中调用file.close()
。 Per default the fs.createWriteStream
is set to autoClose: https://nodejs.org/api/fs.html#fs_fs_createwritestream_path_optionsfs.createWriteStream
设置为 autoClose: https ://nodejs.org/api/fs.html#fs_fs_createwritestream_path_optionsfile.close()
should be called on error.file.close()
。 Maybe this is not needed when the file is deleted ( unlink()
), but normally it is: https://nodejs.org/api/stream.html#stream_readable_pipe_destination_optionsunlink()
)时可能不需要这样做,但通常是: https ://nodejs.org/api/stream.html#stream_readable_pipe_destination_optionsstatusCode !== 200
statusCode !== 200
fs.unlink()
without a callback is deprecated (outputs warning)fs.unlink()
(输出警告)dest
file exists;dest
文件存在; it is overriddenBelow is a modified solution (using ES6 and promises) which handles these problems.下面是一个修改过的解决方案(使用 ES6 和 Promise)来处理这些问题。
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);
}
});
});
}
for those who came in search of es6-style promise based way, I guess it would be something like:对于那些寻找基于 es6 风格的 Promise 方式的人来说,我想它会是这样的:
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));
Based on the other answers above and some subtle issues, here is my attempt.基于上面的其他答案和一些微妙的问题,这是我的尝试。
fs.access
.fs.access
在访问网络之前检查文件不存在。fs.createWriteStream
if you get a 200 OK
status code.200 OK
状态码时才创建fs.createWriteStream
。 This reduces the amount of fs.unlink
commands required to tidy up temporary file handles.fs.unlink
命令的数量。200 OK
we can still possibly reject
due to an EEXIST
file already exists (imagine another process created the file whilst we were doing network calls).200 OK
时,我们仍然可能reject
,因为EEXIST
文件已经存在(想象另一个进程在我们进行网络调用时创建了该文件)。download
if you get a 301 Moved Permanently
or 302 Found (Moved Temporarily)
redirect following the link location provided in the header.301 Moved Permanently
或302 Found (Moved Temporarily)
重定向,则递归调用download
。download
was that they called resolve(download)
instead of download(...).then(() => resolve())
so the Promise
would return before the download actually finished.download
的其他一些答案的问题在于它们调用了resolve(download)
而不是download(...).then(() => resolve())
,因此Promise
会在下载实际完成之前返回。 This way the nested chain of promises resolve in the correct order.const https = require('https');
const fs = require('fs');
/**
* Download a resource from `url` to `dest`.
* @param {string} url - Valid URL to attempt download of resource
* @param {string} dest - Valid path to save the file.
* @returns {Promise<void>} - Returns asynchronously when successfully completed download
*/
function download(url, dest) {
return new Promise((resolve, reject) => {
// Check file does not exist yet before hitting network
fs.access(dest, fs.constants.F_OK, (err) => {
if (err === null) reject('File already exists');
const request = https.get(url, response => {
if (response.statusCode === 200) {
const file = fs.createWriteStream(dest, { flags: 'wx' });
file.on('finish', () => resolve());
file.on('error', err => {
file.close();
if (err.code === 'EEXIST') reject('File already exists');
else fs.unlink(dest, () => reject(err.message)); // Delete temp file
});
response.pipe(file);
} else if (response.statusCode === 302 || response.statusCode === 301) {
//Recursively follow redirects, only a 200 will resolve.
download(response.headers.location, dest).then(() => resolve());
} else {
reject(`Server responded with ${response.statusCode}: ${response.statusMessage}`);
}
});
request.on('error', err => {
reject(err.message);
});
});
});
}
The following code is based on Brandon Tilley's answer :以下代码基于 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();
});
});
Don't make file when you get an error, and prefere to use timeout to close your request after X secondes.遇到错误时不要生成文件,并且更喜欢在 X 秒后使用超时来关闭您的请求。
Hi,I think you can use child_process module and curl command.你好,我想你可以使用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()
In addition,when you want download large、multiple files,you can use cluster module to use more cpu cores.另外,当你想下载大、多文件时,可以使用集群模块来使用更多的cpu核心。
Modern version (ES6, Promise, Node 12.x+ ) works for https/http.现代版本(ES6、Promise、Node 12.x+)适用于 https/http。 ALso it supports redirects 302 & 301. I decided do not use 3rd party libraries due to it can be easy done with standard Node.js libs.
它还支持重定向 302 和 301。我决定不使用 3rd 方库,因为它可以使用标准 Node.js 库轻松完成。
// download.js
import fs from 'fs'
import https from 'https'
import http from 'http'
import { basename } from 'path'
import { URL } from 'url'
const TIMEOUT = 10000
function download (url, dest) {
const uri = new URL(url)
if (!dest) {
dest = basename(uri.pathname)
}
const pkg = url.toLowerCase().startsWith('https:') ? https : http
return new Promise((resolve, reject) => {
const request = pkg.get(uri.href).on('response', (res) => {
if (res.statusCode === 200) {
const file = fs.createWriteStream(dest, { flags: 'wx' })
res
.on('end', () => {
file.end()
// console.log(`${uri.pathname} downloaded to: ${path}`)
resolve()
})
.on('error', (err) => {
file.destroy()
fs.unlink(dest, () => reject(err))
}).pipe(file)
} else if (res.statusCode === 302 || res.statusCode === 301) {
// Recursively follow redirects, only a 200 will resolve.
download(res.headers.location, dest).then(() => resolve())
} else {
reject(new Error(`Download request failed, response status: ${res.statusCode} ${res.statusMessage}`))
}
})
request.setTimeout(TIMEOUT, function () {
request.abort()
reject(new Error(`Request timeout after ${TIMEOUT / 1000.0}s`))
})
})
}
export default download
Kudo to Andrey Tkachenko for his gist which I modified我修改了Andrey Tkachenko的要点
Include it in another file and use将其包含在另一个文件中并使用
const download = require('./download.js')
const url = 'https://raw.githubusercontent.com/replace-this-with-your-remote-file'
console.log('Downloading ' + url)
async function run() {
console.log('Downloading file')
try {
await download(url, 'server')
console.log('Download done')
} catch (e) {
console.log('Download failed')
console.log(e.message)
}
}
run()
Vince Yuan's code is great but it seems to be something wrong. Vince Yuan 的代码很棒,但似乎有问题。
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));
I prefer request() because you can use both http and https with it.我更喜欢 request() 因为你可以同时使用 http 和 https 。
request('http://i3.ytimg.com/vi/J---aiyznGQ/mqdefault.jpg')
.pipe(fs.createWriteStream('cat.jpg'))
✅So if you use pipeline , it would close all other streams and make sure that there are no memory leaks.
✅因此,如果您使用管道,它将关闭所有其他流并确保没有内存泄漏。
Working example:
工作示例:
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.'); } ); });
From my answer to "What's the difference between .pipe and .pipeline on streams" .从我对“流中 .pipe 和 .pipeline 有什么区别”的回答开始。
You can use https://github.com/douzi8/ajax-request#download您可以使用https://github.com/douzi8/ajax-request#download
request.download('http://res.m.ctrip.com/html5/Content/images/57.png',
function(err, res, body) {}
);
Download using promise, which resolve a readable stream.使用 promise 下载,它解析一个可读流。 put extra logic to handle the redirect.
放置额外的逻辑来处理重定向。
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);
}
});
I saw answers using the http , https , and request modules.我看到了使用http 、 https和request模块的答案。 I'd like to add one using yet another native NodeJS module that supports either the http or https protocol:
我想使用另一个支持 http 或 https 协议的本机 NodeJS 模块添加一个:
I've referenced the official NodeJS API, as well as some of the other answers on this question for something I'm doing.对于我正在做的事情,我参考了官方的 NodeJS API,以及关于这个问题的其他一些答案。 The following was the test I wrote to try it out, which worked as intended:
以下是我为尝试而编写的测试,它按预期工作:
import * as fs from 'fs';
import * as _path from 'path';
import * as http2 from 'http2';
/* ... */
async function download( host, query, destination )
{
return new Promise
(
( resolve, reject ) =>
{
// Connect to client:
const client = http2.connect( host );
client.on( 'error', error => reject( error ) );
// Prepare a write stream:
const fullPath = _path.join( fs.realPathSync( '.' ), destination );
const file = fs.createWriteStream( fullPath, { flags: "wx" } );
file.on( 'error', error => reject( error ) );
// Create a request:
const request = client.request( { [':path']: query } );
// On initial response handle non-success (!== 200) status error:
request.on
(
'response',
( headers/*, flags*/ ) =>
{
if( headers[':status'] !== 200 )
{
file.close();
fs.unlink( fullPath, () => {} );
reject( new Error( `Server responded with ${headers[':status']}` ) );
}
}
);
// Set encoding for the payload:
request.setEncoding( 'utf8' );
// Write the payload to file:
request.on( 'data', chunk => file.write( chunk ) );
// Handle ending the request
request.on
(
'end',
() =>
{
file.close();
client.close();
resolve( { result: true } );
}
);
/*
You can use request.setTimeout( 12000, () => {} ) for aborting
after period of inactivity
*/
// Fire off [flush] the request:
request.end();
}
);
}
Then, for example:然后,例如:
/* ... */
let downloaded = await download( 'https://gitlab.com', '/api/v4/...', 'tmp/tmpFile' );
if( downloaded.result )
{
// Success!
}
// ...
External References外部参考
EDIT Information编辑信息
function
declaration, which our contributor has so promptly added.function
声明,该解决方案将不适用于假定的 javascript 用户。 Thanks!download.js (ie /project/utils/download.js) 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应用程序.js
...
// part of imports
const { download } = require('./utils/download');
...
// add this function wherever
download('https://imageurl.com', 'imagename.jpg', () => {
console.log('done')
});
If you are using express use res.download() method.如果您使用的是 express 使用 res.download() 方法。 otherwise fs module use.
否则 fs 模块使用。
app.get('/read-android', function(req, res) {
var file = "/home/sony/Documents/docs/Android.apk";
res.download(file)
});
(or) (或者)
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");
}
});
}
Path : img type : jpg random uniqid路径:img 类型:jpg 随机 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;
}
Without library it could be buggy just to point out.如果没有库,只是指出它可能是错误的。 Here are a few:
这里有几个:
Protocol "https:" not supported.
Protocol "https:" not supported.
Here my suggestion:这是我的建议:
wget
or curl
wget
或curl
等系统工具var wget = require('node-wget-promise'); wget('http://nodejs.org/images/logo.svg');
Writing my own solution since the existing didn't fit my requirements.编写我自己的解决方案,因为现有的不符合我的要求。
What this covers:这包括什么:
http
for HTTP downloads) http
以进行 HTTP 下载)It's typed, it's safer.它是打字的,它更安全。 Feel free to drop the types if you're working with plain JS (no Flow, no TS) or convert to a
.d.ts
file如果您使用纯 JS(无 Flow,无 TS)或转换为
.d.ts
文件,请随意删除类型
index.js index.js
import httpsDownload from httpsDownload;
httpsDownload('https://example.com/file.zip', './');
httpsDownload.[js|ts] https下载。[js|ts]
import https from "https";
import fs from "fs";
import path from "path";
function download(
url: string,
folder?: string,
filename?: string
): Promise<void> {
return new Promise((resolve, reject) => {
const req = https
.request(url, { headers: { "User-Agent": "javascript" } }, (response) => {
if (response.statusCode === 302 && response.headers.location != null) {
download(
buildNextUrl(url, response.headers.location),
folder,
filename
)
.then(resolve)
.catch(reject);
return;
}
const file = fs.createWriteStream(
buildDestinationPath(url, folder, filename)
);
response.pipe(file);
file.on("finish", () => {
file.close();
resolve();
});
})
.on("error", reject);
req.end();
});
}
function buildNextUrl(current: string, next: string) {
const isNextUrlAbsolute = RegExp("^(?:[a-z]+:)?//").test(next);
if (isNextUrlAbsolute) {
return next;
} else {
const currentURL = new URL(current);
const fullHost = `${currentURL.protocol}//${currentURL.hostname}${
currentURL.port ? ":" + currentURL.port : ""
}`;
return `${fullHost}${next}`;
}
}
function buildDestinationPath(url: string, folder?: string, filename?: string) {
return path.join(folder ?? "./", filename ?? generateFilenameFromPath(url));
}
function generateFilenameFromPath(url: string): string {
const urlParts = url.split("/");
return urlParts[urlParts.length - 1] ?? "";
}
export default download;
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');
});
Here's yet another way to handle it without 3rd party dependency and also searching for redirects:这是另一种在没有第三方依赖和搜索重定向的情况下处理它的方法:
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.
});
});
}
For Node with Promise
support, a simple Node shim for (part of the) Fetch API requires only a smattering of extra code compared to other answers:对于支持
Promise
的节点,与其他答案相比,用于(部分)获取 API的简单节点填充程序只需要少量额外代码:
const fs = require(`fs`);
const http = require(`http`);
const https = require(`https`);
module.exports = function fetch(url) {
return new Promise((resolve, reject) => {
const data = [];
const client = url.startsWith("https") ? https : http;
client
.request(url, (res) => {
res.on(`data`, (chunk) => data.push(chunk));
res.on(`end`, () => {
const asBytes = Buffer.concat(data);
const asString = asBytes.toString(`utf8`);
resolve({
arrayBuffer: async () => asBytes,
json: async () => JSON.parse(asString),
text: async () => asString,
});
});
res.on(`error`, (e) => reject(e));
})
.end();
});
};
Which you can then use to whatever you need using normal fetch syntax:然后,您可以使用正常的 fetch 语法将其用于您需要的任何内容:
const fetch = require(`./tiny-fetch.js`);
fetch(`https://placekitten.com/200/300`)
.then(res => res.arrayBuffer())
.then(bytes => fs.writeFileSync(`kitten.jpg`, bytes))
.catch(e => console.error(e));
fetch(`https://jsonplaceholder.typicode.com/todos/1`)
.then(res => res.json())
.then(obj => console.log(obj))
.catch(e => console.error(e));
// etc.
You can try using res.redirect
to the https file download url, and then it will be downloading the file.您可以尝试使用
res.redirect
到 https 文件下载 url,然后它将下载文件。
Like: res.redirect('https//static.file.com/file.txt');
比如:
res.redirect('https//static.file.com/file.txt');
I've found this approach to be the most helpful especially when it comes to pdfs and random other files.我发现这种方法最有帮助,尤其是在涉及 pdf 和随机其他文件时。
import fs from "fs";
fs.appendFile("output_file_name.ext", fileDataInBytes, (err) => {
if (err) throw err;
console.log("File saved!");
});
我们可以使用下载节点模块,它非常简单,请参考下面的https://www.npmjs.com/package/download
I suggest you to use res.download
same as follow:我建议你使用
res.download
如下:
app.get('/download', function(req, res){
const file = `${__dirname}/folder/abc.csv`;
res.download(file); // Set disposition and send it.
});
var requestModule=require("request");
requestModule(filePath).pipe(fs.createWriteStream('abc.zip'));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.