当前位置: 首页 > Web前端 > HTML5

你知道前端是怎么处理图片的吗?

时间:2023-04-05 14:41:08 HTML5

前言作为前端工程师的我们,每天都免不了要和图片打交道。在各大电商平台工作的前端工程师可能感觉更明显。以下是我之前在处理图片时踩过的坑,分享一下我的经验。1.场景复现使用postman请求接口时,在chrome的网络上查看时,返回的图片(二进制)就是这张图片(二进制),也返回这张图片(二进制)。但是调试打印的时候,返回的图片明显是乱码,数据类型发生了变化。想想看,唯一可以更改数据类型的地方是axios。我去翻了一下axios的文档,里面是这样描述的//`responseType`表示服务器响应的数据类型//optionsare'arraybuffer','blob','document','json','text','stream'responseType:'json',//default所以出现乱码的原因是因为:axios默认返回的是json文本形式,强制将二进制图片数据转为json文本形式。一旦找到原因,解决办法就好办了。我们在axios中,默认的responseType返回数据类型是json,改成返回数据类型blob。exportfunctionminiprogramQrcode(params){returnaxios.post(env.MI_URL+'/XXXX/XXX/XXXX',params,//将responseType默认的json改为blob{responseType:'blob',emulateJSON:true})。then(res=>{if(res.data){returnPromise.resolve(res.data)}else{throwres}}).catch(err=>{returnPromise.reject(err)})}next问题就是,如何处理blob对象并显示在前端页面?代码如下:createMiniQrcode(blob){letimg=document.createElement('img')img.onload=function(e){//元素的onload事件触发后,URL对象会被销毁,内存将会被释放。window.URL.revokeObjectURL(img.src)}//浏览器允许URL.createObjectURL()方法为Blob对象生成临时URL。//这个URL以blob://开头,表示它对应一个Blob对象。img.src=window.URL.createObjectURL(blob)document.querySelector('.imgQrCode').appendChild(img)}你以为这就结束了吗?不,不,不。知道如何解决问题是不够的,你需要跳出框框思考。2、发散思路一般来说,后台存储图片有两种方式:一:可以将图片作为独立的文件存储在服务器的指定文件夹中,然后在数据库字段中存储路径;另一种是:将图片转为二进制流,直接存入数据库的Image类型字段。对于第一种存储方式,我们前端可以直接将存储路径赋值给src属性,方便显示。对于第二种存储方式,我们的前端需要将二进制流交给blob对象进行处理,然后通过blobAPI生成一个临时的URL赋值给src属性进行展示。两种存储方式都有对应的解决方案,貌似完美解决了图片显示的问题。但是,我们的业务场景是多样多变的。有时候我们也会遇到这样的场景,比如拖拽图片上传插件后,Blob对象自动返回给你,但是不幸的是,你发现你使用了第三方服务接口只能接收base64格式的数据,是不是有点欲哭无泪?那么图片、url、base64、blob这三种表现形式是否可以进行改造以满足需求呢?1.url转base64url转base64的方法封装//原理:使用canvas.toDataURL转base64urlToBase64(url)的API{returnnewPromise((resolve,reject)=>{letimage=newImage();image.onload=function(){letcanvas=document.createElement('canvas');canvas.width=this.naturalWidth;canvas.height=this.naturalHeight;//将图像插入画布并开始绘制canvas.getContext('2d').drawImage(image,0,0);//resultletresult=canvas.toDataURL('image/png')resolve(result);};//CORS策略,会有跨域问题https://stackoverflow.com/questions/20424279/canvas-todataurl-securityerrorimage.setAttribute("crossOrigin",'Anonymous');image.src=url;//图像加载失败的错误处理image.onerror=()=>{reject(newError('Imagestreamexception'));};}你可以这样调用:letimgUrL=`http://XXX.jpg`this.getDataUri(imgUrL).then(res=>{//转换成base64的图片地址console.log('base64',res)})2.base64转blob方法封装base64转blob//原理:使用URL.createObjectURL来blob对象创建一个临时的URLbase64ToBlob({b64data='',contentType='',sliceSize=512}={}){returnnewPromise((resolve,reject)=>{//使用atob()方法解码数据letbyteCharacters=atob(b64data);letbyteArrays=[];for(letoffset=0;offset{//Convertedblobobjectconsole.log('blob',res)})3.blobtobase64方法封装blobtobase64//原理:利用fileReader的readAsDataURL将blob转换成base64blobToBase64(blob){returnnewPromise((resolve,reject)=>{constfileReader=newFileReader();fileReader.onload=(e)=>{resolve(e.target.result);};//readAsDataURLfileReader.readAsDataURL(blob);fileReader.onerror=()=>{reject(newError('FileStreamError'));};});}你可以这样调用它:this.blobToBase64(blob).then(res=>{//Convertedbase64console.log('base64',res)})ps:上面的方法针对播放图片流进行了优化,感谢原作者贴出了url转base64、base64和blob的demo,其他的会在这里更新。如果你有兴趣,你可以点击这里。三、图像处理方法总结1、后端图像的存储方式前面我们提到,在后端存储图像有两种方式。回顾一下:一:可以将图片作为一个独立的文件存放在服务器的指定文件夹中,然后在数据库字段中存放路径;第二种:可以将图片转为二进制流,直接存入数据库的Image类型字段;那么这两种存储方式哪种更好呢?据我了解,在互联网环境下,访问量大,数据库速度和性能方面很重要。一般在数据库中存储图片的做法比较少,更多的是在数据库中存储图片路径。显示图片时,只需要连接磁盘路径即可加载图片。因为图片是一个很大的领域。一张图片可能是1m到几m。这么大的字段数据会增加数据库的负担,拖慢数据库的速度。在大并发访问的情况下非常重要。这是一种体验。去看dba对数据库性能调优的分析可以得到这样的答案:就是图片不应该存入数据库。所以,如果你公司的后台小??哥经常把图片以二进制的形式存入数据库,然后返回给你对接,你应该知道怎么dui他(滑稽脸)。有关图片或文件如何存储在数据库中的更多信息,请单击此处。2、如何在前端显示图片对于前端:前端显示图片有三种方式:url、base64、blob,哪种更好?优雅又如何?url:一般来说,推荐使用url来显示图片。如果后台传过来的字段是图片路径。base64:如果图片比较大,图片的色彩层次比较丰富,这种方式就不适用了,因为Base64编码的字符串很大,会明显增加HTML页面的体积,影响加载速度。图片如果像loading或者tablelines,体积极小,但是占用一个HTTP请求,很多地方都会用到。非常适合“base64:URLimage”技术来优化!张新旭的详细demo,请点这里。blob:当后端返回一个具体的图片二进制流时,就像我在第一部分的场景复现中所说的,前端使用blob容器来接收它。最好将图像显示为blob。4.感情付出,记录,总结。我会把项目中遇到的问题一点一滴记录整理一下。我相信这些都是散落的枝叶。随着项目经验的增加,这些枝叶最终会长成参天大树。本文观点限于本人目前技术水平,难免有错误之处。欢迎在评论区留言交流,指正。随着技术水平的提高,文章会不定期迭代优化~可以通过以下方式联系我。关于我我的github主页(点击进入)我的掘金主页(点击进入)我的SG主页(点击进入)我的简书主页(点击进入)我的公众号(点击进入或扫描下方二维码)文章回顾:2018年文章写作进度参考:ArrayBufferObjects,BlobObjectsaxios-apiDocumentation