前端通过http获取图片流并转存

一.场景

        昨天公司里面提了一个需求,将竞争对手的sku通过一些手段导入我们自己的数据库,普通数据比较好搞,但是图片这种静态资源我们只能获取到一个url,所以需要进行一次转存。

二.实现

        这里有两个思路,一个是交给后端来做这个事情,但是后端做的话,会暴露我们自己的后端,给对手留下痕迹。第二个就是前端来做,每次使用不同的电脑访问网站来做这个数据转存的操作就给追踪提高难度,因为对方也不知道我们是否是正常的访问资源。

        最终选择了前端来做。第一步,通过http获取到该网站的数据,模拟登录获取token,截取下来他的商品列表数据。这个就不贴代码了,也可以通过不使用代码的方式来实现。

        第二步。将获取到的商品数据里面的图片读取出来并上传

/** 
* @descrip 将blob对象转换成file对象
* @param {Blob} blob  需要转换成文件的blob对象
* @param {string} fileName 文件名
* @param {string} fileType 文件类型
* @return {Promise} 返回一个promise对象,即处理之后的文件对象
**/
const transToFile = async(blob, fileName, fileType) => {
    return new window.File([blob], fileName, { type: fileType })
}

/** 
* @descrip 将互联网上面的图片读取成buffer并且转存至私有的服务器
* @param {string} url  需要转换成的图片的公网地址 eg:https://image.xxx.com/uploads/image/product/62b2babba1c9c_thumb.jpg
* @return {Promise} 返回一个promise对象,即上传成功之后的图片url
**/
const getFileStreamAndUpload = async (url) => {
    return new Promise((resolve, reject) => {
        let suffix = "jpg"
        let fileNameArr = url.split("/")
        let fileName = fileNameArr[fileNameArr.length - 1]
        if (url.split(".").length > 1) {
            suffix = url.split(".")[1]
        }
        // 通过axios读取图片时一定要加上这个responseType,不然是乱码
        axios.get(url, {responseType: 'arraybuffer'}).then(async res => {
            // 构建blob对象
            const blob = new Blob([res.data], { type: `image/${suffix};charset=utf-8` })
            let getFile = transToFile(blob, fileName, `image/${suffix}`)
            getFile.then(async res1 => {
                // 通过FormData将文件提交给后端
                let formData = new FormData()
                formData.append('file', res1)
                formData.append('folderName', "fsImage")
                let res2 = await bar.uploadFile(formData)
                if (res2.code == 200) {
                    resolve(res2.data)
                } else {
                    reject(new Error("图片上传失败"))
                }
            })
        })
    })
}
             // 获取数据成功之后
            const loadingInstance = ElLoading.service({ fullscreen: true })
            // 这里的res.data.data 就是竞争对手的商品列表数据
            let fsData = res.data.data
            for (let i = 0; i < fsData.length; i++) {
                const item = fsData[i];
            // 这里可能会出现跨域请求资源的情况所以使用代理将真实的域名代理到本地的开发服务器上面
                item.productUrl = await getFileStreamAndUpload(item.thumb_path.replace("https://image.xxx.com", "/fsimgapi"))
            }
            console.log(fsData);
            loadingInstance.close()
            ElMessage.success("数据转移成功")

 效果图,这里转换完成之后就直接输出了一个转换后的数组出来,后续根据业务需求将这个数组提交给后端即可。

 

 

三.总结 

其实这种功能最好还是由后端或者nodejs来做,纯前端不可避免的会遇到跨域问题。主要的技术要点就是将网络上面的静态资源通过读取成流的形式放在浏览器缓存里面,然后利用Blob对象跟File对象之间的互相转换,就可以得到一个个的文件对象了,最后通过FormData将数据上传即可。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值