开发一个本地上传图片控件你需要知道的知识点
时间:2023-03-15 14:05:56
科技观察
接到一个“常规”需求:开发一个本地上传图片控件,需要支持三种上传方式:支持打开本地目录,选择本地图片上传,支持图片拖拽上传,支持微信截图上传。我们从工程的角度来看一下用户上传图片的过程:用户选择本地图片,或者拖拽图片,或者通过微信对图片进行截图。这时候我们需要知道用户选择的图片的信息,比如图片的内容,图片的大小,图片的类型等等用户上传的图片。此时,我们需要保存图片。用户查看图片。这时候我们就需要把步骤2保存的图片显示给用户。如何获取图片信息通过input打开本地目录,选择本地图片上传,通过typefile的input标签选择本地图片上传,每次选择不同的图片都会触发onChange事件。为什么我要强调不同的图片,因为当两个选定的图片相同时,就无法触发onchange事件。解决方法:每次处理后手动清空输入值。{console.log('chooseaimage')//获取文件对象constfile=e.target.files[0]letsize=file.sizeif(!file.type.match('image.*')){AntMessage.warning('File\'stypeisnotsupported.Imagesonly.')this.clearImgInputValue()return;}if(size>maxSize){AntMessage.warning('Thesizeoftheimageistoollarge')this.clearImgInputValue()return;}/*eslint-disable*/constreader=newFileReader()//FileReader/*eslint-disable*///转换图片为base64reader.readAsDataURL(file)reader.onload=(arg)=>{//获取base64图片内容constfileStream=arg。target.result/***overwritedosomething**/this.clearImgInputValue()}}拖动图片上传,监听拖动事件,通过拖动相关的DataTransfer对象获取图片信息。DropZone
bindDragEvents=(e)=>{consthandleDragOver=(event)=>{event.stopPropagation()event.preventDefault()event.dataTransfer.dropEffect='copy'}//必须阻止dragenter和dragover事件的默认行为,这样才能触发drop事件constandleFileSelect=(event)=>{event.stopPropagation()event.preventDefault()constfiles=event.dataTransfer.files//文件对象constfile=files[0]constsize=file.sizeconsttype=file.typeif(!type.match('image.*')){AntMessage.warning('File\'stypeisnotsupported.Imagesonly.')return;}if(size>maxSize){AntMessage.warning('Thesizeoftheimageistoollarge')return;}/*eslint-disable*/constreader=newFileReader()/*eslint-disable*///imageConverttobase64reader.readAsDataURL(file)reader.onload=(arg)=>{//获取base64图片内容constfileStream=arg.target.result/***overwritedosomething**/}}constdropZone=document.getElementById('drop-zone');dropZone.addEventListener('dragover',handleDragOver,false);dropZone.addEventListener('drop',handleFileSelect,false);}微信截图上传监听粘贴事件,通过剪贴板对象clipboardData获取图片信息bindClipEvents(){document.addEventListener('paste',(e)=>{console.log('pasteaimage')constclipboard=e.clipboardData//有无内容if(!clipboard.items||!clipboard.items.length){AntMessage.warning('Nocontentintheclipboard')return;}letitem=clipboard.items[0]if(item.kind==='file'&&item.type.match('image.*')){//获取图片文件letimgFile=item.getAsFile()if(imgFile.size>maxSize){AntMessage.warning('Thesizeoftheimageistoollarge')return;}constreader=newFileReader()//将图片转成base64reader.readAsDataURL(imgFile)reader.onload=(arg)=>{//获取base64图片内容constfileStream=arg.target.result/***overwritedosomething**/}}else{AntMessage.warning('File\'stypeisnotsupported.Imagesonly.')}},false)}图片保存方式一般图片使用独立域名服务器,会直接存储在t项目表的数据库。这样做有什么好处?图像访问是一种I/O密集型操作,会消耗服务器资源。独立于Web服务器后,可以减轻Web服务器的压力,方便扩容、容灾、数据迁移。浏览器在同一个域名下有并发策略来限制对图片的请求。cookies是必须的,但是当浏览器发起所有对同一个域名的请求时,http头会自动携带cookies信息,造成带宽浪费,方便负载均衡进行图片访问。可以对图片应用各种缓存策略,方便CDN迁移...总结&优化流程图:不足:虽然我们在项目实践中使用了独立的图片服务器,但下载过程只是通过Web服务器到数据库获取图片地址,但是我们的上传操作还是经过了Web服务器,需要Web服务器上的应用程序进行处理,所以上传过程对Web服务器还是有压力的。幸运的是,我们为图片上传设置了1M的大小限制。同时作为内部系统,没有访问压力,图片上传功能也不是很常见的行为,所以这样做基本没有问题。但最好的解决办法是不管下载还是上传,都直接上独立的图片服务器,以免给web服务器造成额外的压力。