开发一个本地上传图片控件你需要知道的知识点

admin 行业动态 2024-08-06 28

摘要:接了一个「常规」需求:开发一个本地上传图片控件,需要支持三种上传方式: 支持打开本地目录,选择本地图片上传 支持拖曳图片上传 支持微信截图上传 我们先从工程角度来看一下用户上传图片的流程是怎样子的: 用户选择了一张本地图片,或者拖曳了一张图片...

 接了一个「常规」需求:开发一个本地上传图片控件,需要支持三种上传方式:

支持打开本地目录,选择本地图片上传 支持拖曳图片上传 支持微信截图上传

我们先从工程角度来看一下用户上传图片的流程是怎样子的:

用户选择了一张本地图片,或者拖曳了一张图片,或者通过微信截图了一张图片。这时,我们需要知道用户所选择图片的信息,比如图片的内容、图片的大小、图片的类型等。 用户上传图片。这时,我们需要保存图片。 用户查看图片。这时,我们需要把第2步中保存的图片展示给用户。

如何获取到图片信息

通过input 打开本地目录,选择本地图片上传

通过type为file的input标签选择本地图片上传,每次选择不同图片的时候会触发onChange事件。为什么我要强调不同图片,因为当两次选择的图片是一样的情况下,onChange事件无法触发。解决方法:每次处理完后手动置空input的value。

<input id=img-input type=file accept=image/* onChange={this.bindChooseEvents} />  // 置空input value   clearImgInputValue () {     document.getElementById(img-input).value =    }   bindChooseEvents = (e) => {     console.log(choose a image)     // 获取File对象     const file = e.target.files[0]     let size = file.size     if (!file.type.match(image.*)) {       AntMessage.warning(File\s type is not supported. Images only.)       this.clearImgInputValue()       return;     }     if (size > maxSize) {       AntMessage.warning(The size of the image is too large)       this.clearImgInputValue()       return;     }     /* eslint-disable */     const reader = new FileReader()  // FileReader     /* eslint-disable */     // 将图片转换为base64     reader.readAsDataURL(file)     reader.onload = (arg) => {       // 获取到base64图片内容       const fileStream = arg.target.result       /**        * overwrite do something        * */       this.clearImgInputValue()     }   } 

拖曳图片上传

监听拖曳事件,通过拖曳相关的DataTransfer对象获取图片信息。

<div id=drop-zone style={{width: 100px, height: 100px}}>Drop Zone</div> bindDragEvents = (e) => {     const handleDragOver = (event) => {       event.stopPropagation()       event.preventDefault()       event.dataTransfer.dropEffect = copy     }     // 必须阻止dragenter和dragover事件的默认行为,这样才能触发 drop 事件     const handleFileSelect = (event) => {       event.stopPropagation()       event.preventDefault()       const files = event.dataTransfer.files // 文件对象       const file = files[0]       const size = file.size       const type = file.type       if (!type.match(image.*)) {         AntMessage.warning(File\s type is not supported. Images only.)         return;       }       if (size > maxSize) {         AntMessage.warning(The size of the image is too large)         return;       }       /* eslint-disable */       const reader = new FileReader()       /* eslint-disable */       // 将图片转换为base64       reader.readAsDataURL(file)       reader.onload = (arg) => {         // 获取到base64图片内容         const fileStream = arg.target.result         /**          * overwrite do something          * */       }     }     const dropZone = document.getElementById(drop-zone);     dropZone.addEventListener(dragover, handleDragOver, false);     dropZone.addEventListener(drop, handleFileSelect, false);   } 

微信截图上传

监听paste事件,通过剪贴板对象clipboardData获取图片信息。

bindClipEvents() {     document.addEventListener(paste, (e) => {       console.log(paste a image)       const clipboard = e.clipboardData       // 有无内容       if (!clipboard.items || !clipboard.items.length) {         AntMessage.warning(No content in the clipboard)         return;       }       let item = clipboard.items[0]       if (item.kind === file && item.type.match(image.*)) {           // 获取图片文件           let imgFile = item.getAsFile()           if (imgFile.size > maxSize) {             AntMessage.warning(The size of the image is too large)             return;           }           const reader = new FileReader()           // 将图片转换为base64           reader.readAsDataURL(imgFile)           reader.onload = (arg) => {             // 获取到base64图片内容             const fileStream = arg.target.result             /**              * overwrite do something              * */           }       } else {         AntMessage.warning(File\s type is not supported. Images only.)       }     }, false)   } 

如何保存

图片保存一般都采用独立图片独立域名服务器,不会傻乎乎地把图片保存在web服务器上也不会直接存在项目表的数据库中。这样做有什么好处呢?

图片访问是I/O密集型操作,很消耗服务器资源,从Web服务器独立出来后,能够减少Web服务器压力 便于扩容、容灾和数据迁移 浏览器有同域名下的并发策略限制 请求图片一般并不需要cookie,但是浏览器发起的所有同域名请求时,http头部都会自动带上cookie信息,导致浪费带宽 方便对图片访问做负载均衡,可以对图片应用各种缓存策略 方便迁移CDN ...

总结&优化

流程图:

不足:

项目实践中我们虽然采用了独立图片服务器,下载过程只是通过Web服务器去数据库拿到图片地址,但是我们的上传操作仍旧经过了Web服务器,需要Web服务器上的应用程序来处理,所以上传过程仍旧对Web服务器造成压力。所幸的是,我们对图片上传大小进行了1M的大小限制,同时作为内部系统没啥访问压力,而且图片上传功能也并不是很高发的行为,所以这么做基本也不会有啥问题。但是最好的方案还是不管下载上传都直接走独立图片服务器,避免对Web服务器造成额外的压力。

相关推荐

评论列表
关闭

用微信“扫一扫”