在爬取壁纸的时候,需要将其下载到本地,本着不重复造轮子的信念,想着是否有成熟的三方库可以直接调用,逛了一圈后,发现最近更新是在三年前!o(╯□╰)o
无奈,只能自己“造个轮子”了……
一般的方式是先调用http
接口发起请求爬取图片,然后再调用文件接口保存图片。如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
http.get(url, (req, res) => {
let imgData = '';
req.on('data', (chunk) => {
imgData += chunk;
})
req.setEncoding('binary');
req.on('end', () => {
writeFile(savePath, imgData, 'binary', (err) => {
...
})
})
})
或者调用creatWriteStream
:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
http.get(url, (res) => {
const ws = createWriteStream('/path/to/save/wallpaper.jpg')
res.pipe(ws)
ws.on('finish', () => {
...
});
ws.on('error', () => {
...
});
})
第2种方式虽然已经较前一种更为优雅、高效,但还是有些繁琐,毕竟,依然包含了3个回调函数,对于流程控制或者错误处理,无疑都增加了不少负担。因此,需要一种更科学、合理、有效的方式。
查看Nest.js的API,发现HttpService
中有一个axiosRef
方法,就是它了!最终版代码如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
async download(url: string, path: string) {
const writer = createWriteStream(path);
const response = await this.httpService.axiosRef({
url,
method: 'GET',
responseType: 'stream'
});
response.data.pipe(writer);
return new Promise((resolve, reject) => {
writer.on('finish', resolve);
writer.on('error', reject);
});
}
此方式充分利用了createWriteStream
、HttpService
、Promise
等新特性,尤其是其中的管道操作,简直是效率、性能利器;而最后的回调处理也完美地转换成了Promise
的resolve
、reject
方式,充分发挥了ES6的异步编程优势。
如此,再去实现图片的下载就很容易了:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
const response = await this.httpService.axiosRef({
url: imageUrl,
method: 'GET',
responseType: 'stream'
});
res.set({
'Content-Type': imageType || 'image/jpeg',
'Content-Disposition': `attachment; filename=${fileName}`
});
response.data.pipe(res);
完美![]~( ̄▽ ̄)~*