当前位置: 首页 > 科技观察

基于业务场景的图片-文件上传方案总结

时间:2023-03-15 23:50:26 科技观察

前言图片/文件上传组是企业项目开发中必不可少的环节之一,但是任何一个用户模块都会有图片/文件上传需求,在很多情况下也是其中之一三方组件库(antdesign、elementui)中的基础组件。接下来笔者将带大家从零开始实现一个图片/文件上传组件,并扩展一个更强大的上传组件。你会收获常用图片上传功能实现方案手写一个图片/文件上传组件如何将裁剪功能集成到上传组件中如何扩展内容平台/可视化平台下的图片自主解决方案如何扩展更强大的图片上传解决方案作为一名前端工程师,项目问题的解决是我们的基本职责之一,就是能够利用所学的知识去解决项目开发中的问题和需求。这也是我们在职业生涯中必须经历的第一个阶段,即适应期。如果我们想要继续晋升,就需要不断的升级怪物,掌握各种技能,这样以后遇到问题的时候,才能用最好的方案高效的解决问题,也就是第二个阶段——发展期。为了更快的进入开发未来,我们需要不断提升自己的技术深度和广度,能够纵向的考虑问题的本质,横向的提出问题的多种解决方案,最终选择一个最优的方案来实现.要做到这一点,我们需要对问题进行深入的思考和回顾,接下来笔者将介绍几种常用的图片上传解决方案,以扩展你的广度。1、常用的图片上传方案从web1.0时代开始,我们使用最多的上传方案是form表单,我们只需要在form中写各种input(input元素),定义上传服务器地址(action).表单类似如下:

在XHR技术还没有普及的时候,我们大多数人会选择上面的解决方法,唯一的缺点就是提交后页面会刷新,用户体验不是很好,可能会丢失一些数据,不过还是有解决方法的,就是form+iframe技术。1.1form+iframe方案form+iframe方案的基本思路是,我们提交的动作是在父页面触发的,但是form指向一个iframe,可以实现局部刷新。现在有些场景还在用这个方案。具体原理如下:以上两种方案都可以实现传统表单提交下的局部刷新功能,但是方案一需要单独维护iframe表单,所以我一般采用方案二,兼容性可以达到IE9(虽然现在兼容IE浏览器已经没有意义了,但还是要了解一下)1.2XHR盛行ajax+formData的方案之后,我们可以很方便的使用ajax来实现异步请求。对于文件上传,我们也可以更灵活的使用ajax和formData,逐渐脱离对原生form表单的依赖。FormData对象是用来将数据编译成键值的,为了使用XMLHttpRequest发送数据,主要用于发送表单数据,但也可以用来发送键控数据(keyeddata),独立于表格。如果表单的enctype属性设置为multipart/form-data,则将使用表单的submit()方法发送数据,使发送的数据具有相同的表单。先来看一个使用formData上传文件的简单例子:letformData=newFormData();//HTML文件类型输入,由用户选择formData.append("userfile",fileInputElement.files[0]);letrequest=newXMLHttpRequest();request.open("POST","http://http://io.nainor.com/h5/form");request.send(formData);上面5行代码就足以将文件通过FormData上传到服务器,是不是很简单?笔者之前的文章基于react/vue开发了一款面向程序员的朋友圈应用,采用了该方案。如果你有兴趣,你可以学习和研究它。文件上传也很简单。这里我们以axios为例。具体实现如下:constformData=newFormData()for(leti=0;i{const[fileList,setFileList]=useState([{uid:'-1',name:'image.png',status:'done',url:'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',},]);constonChange=({fileList:newFileList})=>{setFileList(newFileList);};constonPreview=asyncfile=>{letsrc=file.url;if(!src){src=awaitnewPromise(resolve=>{constreader=newFileReader();reader.readAsDataURL(file.originFileObj);reader.onload=()=>resolve(reader.result);});}constimage=newImage();image.src=src;constimgWindow=window.open(src);imgWindow.document.write(image.outerHTML);};return({fileList.length<5&&'+Upload'});};ReactDOM.render(,mountNode);以上只是一个裁剪上传图片的基本示例,当然antd-img-crop还提供了更灵活的配置,方便我们设计更灵活强大的裁剪效果。当然,我们也可以使用react-cropper来实现,它提供了更灵活的裁剪控制和裁剪实时预览功能,如下图所示:3.内容平台/可视化平台下的图片自主权对于内容平台或可视化平台,单纯上传图片是不能满足用户需求的,因为内容/可视化平台更注重图片的选择和使用,对图片的要求也非常高。毕竟用户自己上传的资源有限,往往无法满足用户对内容发布或视觉设计的需求。因此,这类平台往往会提供图片素材库的功能,用户可以在素材库中搜索海量图片。满足自己的需求,而且经常这样,还不如留住用户,增加用户粘性。基于以上场景,产品经理经常会提出这样的需求:能否提供可选方案,用户可以自行上传图片,使用我们提供的图片库资源呢?这时候,有经验的前端往往会说:安排!在设计这个功能之前,我们往往不得不参考其他已有的实现。这里我们举几个例子,如下图所示:以上案例在上面我们可以发现,用户上传图片的时候,有两个可选的选项,一个是本地上传,一种是直接在图片库中选择,所以我们的解决方法是类似的。图片库可以作为通用功能封装到文件上传组件中,也可以组合封装,各自独立使用或组合使用。对于H5-Dooring对图片库的封装是作为一个通用服务实现的,即每当使用上传组件时,总会有一个可选的按钮可以从图片库中选择。实现也很简单,就是扩展一个Layer,使用Modal+Tab做图片选择界面,选择完成后,手动设置图片的地址给上传组件。代码如下:handleImgSelected=()=>{constfileList=[{uid:uuid(8,16),name:'h5-dooringimagelibrary',status:'done',url:this.state.curSelectedImg,},];this.props.onChange&&this.props.onChange(fileList);this.setState({fileList,wallModalVisible:false});};这里使用了antd的表单组件的受控模式。4.图片上传组件扩展上面介绍的方案对于基本的使用场景来说是完全够用的,但是如果是内容网站或者可视化搭建平台,由于我们的配置随时可能下发到公网,这就会涉及到问题的内容安全。一旦用户配置了非法图片信息,可能会牵连到平台的提供,所以我们也需要提供一套完整的例如用户配置或发布内容后,需要经过审核后方可发布可以正式在线发表,但是完全依赖人工审稿效率比较低,所以这个时候就需要寻找机器自动审稿的解决方案。比如阿里云和腾讯云都提供图像识别等服务。我们可以将这些服务集成到我们的组件中,实现真正的业务自治,让我们更安全地进行企业运营和发展。还有一个需求就是用户对上传的图片有编辑需求,我们也可以提供图片的在线编辑功能,类似下面的解决方案:我们可以让用户自己设计,给自己选择的图片加上水印,是不是更有趣?5.综上所述,以上教程作者已经集成到H5-Dooring中了。对于一些比较复杂的交互功能,也可以通过合理的设计来实现。大家可以自行探索研究。本文转载自微信公众号《趣谈前端》