JavaScript实现将图片地址转成文件流并上传
作者:橙某人
写在开头
最近,小编在业务中遇到一个图片转存的场景。
领导:大概过程就是,接口会给我返回一个图片列表数据,图片路径是全路径,但是路径中的域名是其他系统的,必须要在用户选择图片的时候将图片重新转存到自个的系统上,防止其他系统删除图片对此有影响。
我:Em...很合理的需求。
(但是,和有什么关系?我只是一个前端小菜鸡呀,不祥的预感.......)
我:(卑微提问)这个过程不是放后端做比较合理一点?
后端大哥:前端不能做?
我:可以可以,只是...这个好像会跨域?
后端大哥:已经配置了请求头('Access-Control-Allow-Origin': '*'
)。
我:哦,好的,我去弄一下。(*******此处省略几万字心理活动内容)
第一种(推荐)
那么,迫于......不,我自愿的,我们来看看前端要如何完成这个转成过程,代码比较简单,直接贴上来瞧瞧:
async function imageToStorage(path) { // 获取文件名 const startIndex = path.lastIndexOf('/'); const endIndex = path.indexOf('?'); const imgName = path.substring(startIndex + 1, endIndex); // 获取图片的文件流对象 const file = await getImgToFile(path, imgName); // TODO: 将File对象上传到其他接口中 } /** * @name 通过fetch请求文件,将文件转成文件流对象 * @param { string } path 文件路径全路径 * @param { string } fileName 文件名 * @returns { File | undefined } */ function getImgToFile(path, fileName) { const response = await fetch(path); if (response) { const blob = await response.blob(); const file = new File([blob], fileName, { type: blob.type }); return file; } }
上述方式,在后端配置了允许跨域后,正常是没有什么问题的,也是比较好的一种方式了。
但是,在小编实际第一次编码测试后,却还是遇上了跨域。
一猜应该就是后端实际还没配置好,问了一下。
后端大哥:还没部署,一会再自己试试。
我:嗯嗯。
第二种
等待的过程,小编又在网上找了找了,找到了第二种方式,各位看官可以瞧瞧:
/** @name 将图片的网络链接转成base64 **/ function imageUrlToBase64(imageUrl: string, fileName: string): Promise<File> { return new Promise(resolve => { const image = new Image(); // 让Image元素启用cors来处理跨源请求 image.setAttribute('crossOrigin', 'anonymous'); image.src = imageUrl + '&v=' + Math.random(); image.onload = () => { const canvas = document.createElement('canvas'); canvas.width = image.width; canvas.height = image.height; const context = canvas.getContext('2d')!; context.drawImage(image, 0, 0, image.width, image.height); // canvas.toDataURL const imageBase64 = canvas.toDataURL('image/jpeg', 1); // 第二个参数是压缩质量 // 将图片的base64转成文件流 const file = base64ToFile(imageBase64, fileName); resolve(file); }; }); } /** @name 将图片的base64转成文件流 **/ function base64ToFile(base64: string, fileName: string) { const baseArray = base64.split(','); // 获取类型与后缀名 const mime = baseArray[0].match(/:(.*?);/)![1]; const suffix = mime.split('/')[1]; // 转换数据 const bstr = atob(baseArray[1]); let n = bstr.length; const u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } // 生成文件流 const file = new File([u8arr], `${fileName}.${suffix}`, { type: mime, }); return file; }
这第二种方式由于要先把图片绘制到 canvas
再去转成 base64
再去转成文件流,小编用 console.time
稍微测了一下,每次转化过程都要几百毫秒,图片越大时间越长,挺影响性能的。
所以,小编还是推荐使用第一种方式,当然,最稳妥的方案是后端去搞最好了。
网上很多都说第二种方式可以直接绕过跨域,各种谈论。
主要就是这个 crossOrigin
属性。MDN解释
它原理是通过了 CORS
或者可以再看看这个解释:传送门
到此这篇关于JavaScript实现将图片地址转成文件流并上传的文章就介绍到这了,更多相关JavaScript图片地址转文件流内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!