资讯专栏INFORMATION COLUMN

【Copy攻城狮日志】Node.js之http下载图片失败

darkbaby123 / 1333人阅读

摘要:当用户或搜索引擎向网站服务器发出浏览请求时,服务器返回的数据流中头信息中的状态码的一种,表示本网页永久性转移到另一个地址。通过在源代码中添加日志输出,我们也能清楚地看到的状态码。

Created 2019-4-5 22:24:33 by huqi
Updated 2019-4-5 23:23:56 by huqi


↑开局一张图,故事全靠编↑

从解答一个知否上的问题说起

有时候,自己就像自己在知否的签名一样--我以为的就是我以为的?一直以来,对前端技术的一知半解一叶障目,导致我遇到问题总是片面,比如这次,就翻车了。技术水平就那样,然后我居然还想着帮人家解答,这不是误人子弟吗?昨天解答的这个问题,是关于node.js的http方法,根据Url获取网络图片写入到本地文件夹,这个需求我之前是玩过的,但用的是Copy&Paste的代码,也没有细细研究源码,只知道用的是request的模块,不过这次的哥们没有依赖任何第三方模块,只是用的内置的http模块。他遇到的问题就是上图所见,有一张图片没有下载成功无法正常显示。具体问题见@夜鹰 :用Node.js读取远程的图片文件并写入本地?

通过内置http模块下载图片源码

引入内置http模块发起请求获取文件

引入内置fs模块写入文件

const http = require("http")
const fs = require("fs")

const urlArr = [
"http://img.zcool.cn/community/01e505554437be0000019ae95582a2.jpg@900w_1l_2o_100sh.jpg",
"http://static.pig66.com/uploadfile/2017/1102/20171102095531217.png",
]

urlArr.forEach(url => {
    getImg(url)
})

function getImg(url, name) {
    http.get(url, {encoding: null}, res => {
        let img = []
        let size = 0
        // 将图片地址以【.】符号分割,取最后一项,即为格式后缀
        const _arr = url.split(".")
        const format = _arr[_arr.length - 1]
        // 如果没有传入图片名字,则使用随机数
        const _name = name ? name : "image-" + Math.floor(Number(new Date()) * Number(Math.random()))
        res.on("data", chunk => {
            img.push(chunk)
            size += chunk.length
        })
        res.on("end", () => {
            // 合并 Buffer
            const buffer = Buffer.concat(img, size)
            fs.writeFileSync(`img/${_name}.${format}`, buffer, (err) => {
                if (err) {
                    return console.error(err);
                }
                console.log("数据写入成功!");
            })
        })
    })
}

对来说,起初我以为是文件太大的原因,因为通过输出查看到Buffer数据中断并直接结束了。后来我试了下1M左右的图片,完全能够成功下载,然而,打脸啪啪啪。接下来,我草率地下了结论,并丢给博主一段使用第三方模块request的同样功能的实现(见历史版本:共被编辑 4 次)。真相纠结是怎样的?另一位答主@啊哦 已经给出了相当明确的答案!

“罪魁祸首”--301重定向
301重定向()页面永久性移走)是一种非常重要的“自动转向”技术。网址重定向最为可行的一种办法。当用户或搜索引擎向网站服务器发出浏览请求时,服务器返回的HTTP数据流中头信息(header)中的状态码的一种,表示本网页永久性转移到另一个地址。

打开图片链接:http://www.pig66.com/uploadfi...,通过查看Network,我们清晰地看到源图片有做301重定向。通过在源代码中添加日志输出,我们也能清楚地看到301的状态码。

既然问题的根源已经找到,那就对症写bug,如果是301的话获取请求返回的真实地址再次发起请求。

        const { statusCode } = res
        if ( statusCode === 301 ) {
            const url = res.headers["location"]
            return getImg(url)
        }

修改后的代码:

const http = require("http")
const fs = require("fs")

const urlArr = [
"http://img.zcool.cn/community/01e505554437be0000019ae95582a2.jpg@900w_1l_2o_100sh.jpg",
"http://static.pig66.com/uploadfile/2017/1102/20171102095531217.png",
]

urlArr.forEach(url => {
    getImg(url)
})

function getImg(url, name) {
    http.get(url, {encoding: null}, res => {
        const { statusCode } = res
        console.log(statusCode)
        if ( statusCode === 301 ) {
            const url = res.headers["location"]
            return getImg(url)
        }
        let img = []
        let size = 0
        // 将图片地址以【.】符号分割,取最后一项,即为格式后缀
        const _arr = url.split(".")
        const format = _arr[_arr.length - 1]
        // 如果没有传入图片名字,则使用随机数
        const _name = name ? name : "image-" + Math.floor(Number(new Date()) * Number(Math.random()))
        res.on("data", chunk => {
            img.push(chunk)
            size += chunk.length
        })
        res.on("end", () => {
            // 合并 Buffer
            const buffer = Buffer.concat(img, size)
            fs.writeFileSync(`img/${_name}.${format}`, buffer, (err) => {
                if (err) {
                    return console.error(err);
                }
                console.log("数据写入成功!");
            })
        })
    })
}

成功拿到图片,并能直观的感受到301重定向之后又发起了一次请求,

后记

这两天朋友托我写两个简单的页面,我发现自己啥也不会!想想我,居然还这么热心地去帮人解答,真的是误人子弟害人不浅。谨以此次经历深刻反省自我,对被我坑过的各位表示深切的歉意。同时,也希望各位大佬不惜多多赐教!最后,祝@jsliang 生日快乐!写在生日,一年前端拼搏记

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/103263.html

相关文章

  • Copy城狮日志】CML5分钟入门多端统一框架

    摘要:开局一张图,故事全靠编是啥变色龙又是啥自从有小程序以来,小程序的第三方框架便孕育而生,从原始时代的只基于微信小程序多如今多端统一开发框架,可以说前端技术从年到年又发生了天翻地覆的变化。 Created 2019-4-6 21:57:17 by huqi Updated 2019-4-7 22:54:55 by huqi showImg(https://segmentfault.c...

    MycLambert 评论0 收藏0
  • Copy城狮日志】借助Taro暴改Nideshop实现电商支付宝小程序雏形

    摘要:接下来,在支付宝小程序开发者工具中打,不出意外能跑起来一个电商支付宝小程序雏形。地址以上是我这个攻城狮对使用转换原生微信小程序为支付宝小程序的一次微不足道的实践。 showImg(https://segmentfault.com/img/bVbnCCN?w=1818&h=931);↑开局一张图,故事全靠编↑ 从一个需求说起 作为底层的程序猿,哦不,我连猿都算不上,混的好的叫码神,混得一...

    gnehc 评论0 收藏0
  • Copy城狮日志】踩坑小程序can't read property 'of

    摘要:根据当时的情境,是在微信开发者工具中删掉该小程序然后重新载入就解决了,大家给出的结论是微信小程序开发者工具的。 Created 2019-4-2 22:17:34 by huqiUpdated 2019-4-2 23:17:34 by huqishowImg(https://segmentfault.com/img/bVbqOLH?w=1526&h=818); ↑开局一张图,故事全靠编...

    hsluoyz 评论0 收藏0
  • Copy城狮日志】踩坑小程序使用svg作为图标

    摘要:可以使用网络图片,或者,或者使用标签。这个是常识,连入门级小程序员都知道的。那我究竟写了个什么毫无疑问,一定是在中直接引用了本地图片。虽然可以将图标转化为字体应用,但对于我来说,就使用那么几个图标,实在是不想引用一大堆等文件,只想用下。 Created 2019-4-4 22:02:27 by huqi Updated 2019-4-4 23:12:34 by huqi show...

    Miracle_lihb 评论0 收藏0
  • Copy城狮日志】踩坑小程序canvas的显示层级问题

    摘要:依旧是很简单的需求,但是对于资深的攻城狮来说,除了布局,其他的就只能去了。特别是真机跑的时候,问题特别多。还是坑在基础不牢固,文档看得不深入,对小程序原生组件应该注意的事项把握不准,才会掉入这个非常基础的坑。 Created 2019-4-3 18:29:53 by huqiUpdated 2019-4-3 19:12:22 by huqi showImg(https://segmen...

    Coly 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<