fetch获取线上图片引发的思考
背景
起因是想下载一个套图但是貌似要 VIP 会员才能下载的样子,于是抱着侥幸的心理点开 F12 看了一眼,发现居然 src 就是图片的真实 uri,并且整个套图文件名数字是累加的, 嘴角疯狂上扬的同时决定写个脚本白嫖一下.
实现过程
该过程主要还是对 fetch
这个 api 的探究, 使用了能够运行在 node 中的node-fetch
, 以下三种方法对图片音频进行下载测试均正常
stream
使用fetch
返回的是一个Promise
对象且resolve
状态下的res.body
是一个readablestream
可读流,可以直接利用管道接到创建的可写流中.
1 |
|
buffer()
利用node-fetch
相较浏览器fetch
特有的 buffer()方法
1 |
|
arrayBuffer()
我们知道 node 中传输二进制数据需要通过buffer
进行存储, 而 fetch 只提供了res.arrayBuffer()
的方法, 所以在使用arrayBuffer()
后还需要使用Buffer.from
将arrayBuffer
转化为buffer
,这也是第二种方法简化的操作
1 |
|
到这里已经对于获取远程文件的方法已经讲完了,下面是个人对其中不理解的部分的笔记
fetch
对比 ajax
之前一直觉得 fetch 与 $.ajax,axios 一样,对上面案例实践后发现还是自己菜了.
根据 MDN 上的描述:
Fetch API 提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的一些具体部分,例如请求和响应。它还提供了一个全局 fetch() 方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源。这种功能以前是使用 XMLHttpRequest 实现的。
也就是说 fetch 实际上是在Promise
出现来解决callback hell
前提下的一个新的异步获取资源的方案.
而 fetch
与传统 ajax 的区别是
- 除非出现网络故障或请求被阻止的情况下,
fetch
会将Promise
状态置为reject
,其余像响应状态码404
,500
,fetch
都会将状态标记为resolve
,但会将resolve
的响应对象的ok
属性置为false
fetch
不会接收跨域的cookie
,即跨域响应头中的set-cookie
将被忽略fetch
默认不会跨域时发送cookie
,(ajax 也是一样的), 默认fetch
的credentials
为same-origin
fetch
跨域
fetch 跨域需要后端配合CORS
,后端需要对以下响应头字段进行设置,否则会报错
1 |
|
之后,fetch
设置fetch(url, {mode: 'cors'})
即可进行跨域
若设置为{mode: 'no-cors'}
, fetch
不会进行报错,但会把Promise
的resolve
会返回ok: false, type: 'opaque'
表明你没有权限访问
- Q: 提问! 后端没有提供
CORS
,fetch
需要怎么跨域? - A: 那就不要使用
fetch api
, 建议JSONP
.
arrayBuffer, Buffer, typedArray
对于arrayBuffer
与typedArray
都属于二进制数组,对于详细内容可以参考掘金的这篇文章:
掘金文章
这里做简述:
1 |
|
下面这张图也能看出两者的关系:
Buffer 与 TypedArray
编写脚本时便有一个困扰,Buffer
与arrayBuffer
有啥关系? 这里记录一下.
Buffer
是对Uint8Array
的实现
Buffer
对Uint8Array
的相关 API 进行了实现,但 node 对Buffer
类进行了优化,使之更适合在 node 下运行Buffer
并不是完全兼容TypedArray
实现
Buffer
同样是一个Uint8Array
类型数组实例。但它与 ES6 中的类型数组规范并不完全兼容,如:ArrayBuffer#slice()
会创建一个分隔部分数据的拷贝,而Buffer#slice()
会创建一个从 Buffer 中拷贝数据的视图,相对来说Buffer#slice()
更高效。Buffer
可以与类型数组共享内存区
可以从TypedArray
的.buffer
属性或new ArrayBuffer()
创建一个 Buffer 对象。该对象会与类型数组共享内存区:
1 |
|
回到开头那个困扰, 除了底层规范不完全兼容, 我们可以以Uint8Array
来看待Buffer
,并可以通过Buffer.buffer
的方式获得ArrayBuffer
.
延伸的实践
谈了那么多关于二进制数据的话题,现在对掘金文章中的一些小案例进行一下实践
获取远程图片并转换为 base64 格式
to be continue…