网站内容管理系统上传图片( 从零实现一款图片/文件上传组件以及扩展出更强大的上传方案)

优采云 发布时间: 2022-02-11 08:14

  网站内容管理系统上传图片(

从零实现一款图片/文件上传组件以及扩展出更强大的上传方案)

  

  前言

  图片/文件上传组是企业项目开发中不可缺少的环节之一。任何涉及用户模块的东西都会有图像/文件上传要求。也是很多第三方组件库(ant design、element ui)中的基础组件。一.接下来,笔者将带大家从零开始实现一个图片/文件上传组件,扩展一个更强大的上传组件。

  你会得到文字

  作为前端工程师,解决项目问题是我们的基本职责之一。我们可以利用我们所掌握的知识来解决项目开发中的问题和需求。这也是我们职业生涯要经历的第一个阶段,即——适应期。想要继续晋级,就需要不断的打怪升级,掌握各种技能,这样以后遇到问题的时候,才能用最好的办法高效的解决问题,也就是第二阶段——发展期。

  为了更快地进入发展期,我们需要不断提高我们技术的深度和广度,可以纵向横向考虑问题的性质,提出多种解决问题的方案,最终选择一个最优的解决方案来实现。为此,我们需要对问题进行深入思考和回顾。接下来,笔者将介绍几种常用的图片上传方案,以扩大大家的视野。

  1. 常用图片上传方案

  从web1.0时*敏*感*词*始,最常用的上传方案就是form表单。我们只需要在表单中编写各种输入(输入元素),并定义上传服务器地址(action)即可,表单可以类似如下:

  在 XHR 技术还没有普及的时候,我们大多数人都会选择上面的方案。唯一的缺点是提交后页面会刷新,用户体验不是很好,可能会造成部分数据丢失,不过还是有解决办法的,就是form+iframe技术。

  1.1表单+iframe解决方案

  form+iframe方案的基本思想是我们的提交动作是在父页面触发的,但是form表单指向一个iframe,可以实现部分刷新。现在有些场景还在使用这个方案,具体原理如下:

  

  以上两种方案都可以实现传统表单提交下的局部刷新功能,但是第一种方案需要单独维护iframe表单,所以我一般使用第二种方案,兼容性可以达到IE9(虽然是现在兼容IE浏览器的不多,但还是需要了解)

  1.2 ajax + formData 方案

  在 XHR 盛行之后,我们可以很方便地使用 ajax 来实现异步请求。对于文件上传,我们也可以更加灵活的使用ajax和formData,逐步摆脱对原生form的依赖。

  FormData 对象用于将数据编译成键值对,以便使用 XMLHttpRequest 发送数据。它主要用于发送表单数据,但也可用于发送键控数据,与表单无关。如果表单的enctype属性设置为multipart/form-data,则使用表单的submit()方法发送数据,使发送的数据具有相同的表单。

  我们先来看一个使用formData上传文件的简单例子:

  let formData = new FormData();

// HTML 文件类型input,由用户选择

formData.append("userfile", fileInputElement.files[0]);

let request = new XMLHttpRequest();

request.open("POST", "http://http://io.nainor.com/h5/form");

request.send(formData);

  以上仅5行代码就实现了通过formData将文件上传到服务器。不是很简单吗?作者以前的文章。

  实现多文件上传也很简单。这里我们以 axios 为例。具体实现如下:

  const formData = new FormData()

for(let i=0; i< files.length; i++) {

formData.append(`file_${i+1}`, files[i].file)

}

axios({

method: &#39;post&#39;,

url: &#39;/files/upload/tx&#39;,

data: formData,

headers: {

&#39;Content-Type&#39;: &#39;multipart/form-data&#39;

}

});

  这里需要注意的是,对于多文件上传,必须在请求的http头中将Content-Type设置为multipart/form-data。当然,您也可以基于以上原则,实现更符合您业务需求的文件上传组件,如预览、限流等。

  1.3 第三方组件实现

  为了更高效快速的开展业务,有时我们可以选择第三方比较成熟的方案,比如antd的上传组件,比如element ui的上传组件,这里笔者总结了几个比较实用强大的解决方案,你可以感受一下:

  antd/element 的上传组件

  FilePond 可以上传任何内容,并且能够优化图像以加快上传速度,同时提供流畅的用户体验

  Web Uploader 百度WebFE(FEX)团队开发了一个基于HTML5并辅以FLASH的简单现代文件上传组件

  vue-simple-uploader 一个强大漂亮的基于vue的文件上传组件

  我们可以通过上面提供的第三方组件库,结合自己服务器的配置,轻松实现一个强大的上传组件。

  2. 将裁剪功能集成到图片上传组件中

  对于图片上传组件,我们往往无法确定用户上传的是什么,所以需要提前进行限制,比如限制图片大小、图片格式、图片比例等,以满足我们的业务标准。图片大小和图片格式的限制很容易实现,但是对于图片比例,我们不能指望用户来处理这个,因为这会大大增加用户使用网站的负担,所以我们可以提供一个函数允许用户在线剪切图像。如下所示:

  

  以上截图来自H5-Dooring在线编辑器的图片上传组件。用户上传后,我们会出现图片裁剪界面。我们将指定图像的比例并允许用户自由裁剪。笔者将使用基于antd的上传组件配合antd-img-crop带你实现在线图片裁剪功能。具体代码实现如下:

  import React, { useState } from &#39;react&#39;;

import { Upload } from &#39;antd&#39;;

import ImgCrop from &#39;antd-img-crop&#39;;

const Demo = () => {

const [fileList, setFileList] = useState([

{

uid: &#39;-1&#39;,

name: &#39;image.png&#39;,

status: &#39;done&#39;,

url: &#39;https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png&#39;,

},

]);

const onChange = ({ fileList: newFileList }) => {

setFileList(newFileList);

};

const onPreview = async file => {

let src = file.url;

if (!src) {

src = await new Promise(resolve => {

const reader = new FileReader();

reader.readAsDataURL(file.originFileObj);

reader.onload = () => resolve(reader.result);

});

}

const image = new Image();

image.src = src;

const imgWindow = window.open(src);

imgWindow.document.write(image.outerHTML);

};

return (

{fileList.length < 5 && &#39;+ Upload&#39;}

);

};

ReactDOM.render(, mountNode);

  以上只是裁剪和上传图片的一个基本示例。当然,antd-img-crop 也提供了更灵活的配置,方便我们设计更灵活、更强大的裁剪效果。当然,我们也可以使用 react-cropper 来实现,它提供了更灵活的裁剪控制和实时裁剪预览功能,如下图所示:

  

  3. 内容平台/可视化平台下的图像自治

  对于内容平台或可视化平台来说,单纯的上传图片并不能满足用户的需求,因为内容/可视化平台更注重图片的选择和使用,对图片的要求很高。用户对内容发布或视觉设计的需求,此类平台往往提供图片素材库功能。用户可以在素材库中搜索海量图片来满足自己的需求,往往这样更能留住用户,增加用户粘性。

  基于以上场景,产品经理经常会提出以下需求:能否提供可选方案,让用户自行上传图片或使用我们提供的图片库资源?这时候,有经验的前端经常会说:安排!

  在设计这个功能之前,我们经常会参考其他现有的实现。这里我们举几个例子,如下图所示:

  

  

  

  在上述情况下,我们可以发现用户上传图片的时候有两个可选的选项,一个是本地上传,一个是直接从图片库中选择,所以我们的方案类似,可以打包图片库统一上传到文件中。作为组件中的通用功能,也可以组合封装,每个可以单独使用,也可以组合使用。

  对于H5-Dooring对图片库的封装,是作为通用服务实现的,即每当使用上传组件时,都会有一个可选择的图片库选择按钮。实现方案也很简单,就是在上传组件中间扩展一层,使用Modal+Tab做图片选择界面,选择完成后手动设置图片的地址给上传组件. 代码如下:

  handleImgSelected= () => {

const fileList = [

{

uid: uuid(8, 16),

name: &#39;h5-dooring图片库&#39;,

status: &#39;done&#39;,

url: this.state.curSelectedImg,

},

];

this.props.onChange && this.props.onChange(fileList);

this.setState({ fileList, wallModalVisible: false });

};

  这里使用antd的表单组件的受控方式。

  4. 图片上传组件扩展

  上述方案对于基本的使用场景来说已经足够了,但是如果是内容网站或者可视化搭建平台,由于我们的配置随时可能下发到公网,这就涉及到内容安全问题。一旦用户配置非法图片信息,平台可能会受到牵连,因此我们还需要提供完善的审核机制。例如,用户配置或发布内容后,需要经过审核才能正式上线发布。,但是完全依靠人工审核效率相对较低,所以这时候我们需要寻找机器自动化审核的解决方案。比如阿里云和腾讯云提供了图像识别等服务,我们可以将这些服务集成到我们的组件中。,实现真正的业务自治,

  另一个需求是用户对上传的图片有编辑需求,我们也可以提供图片在线编辑功能,类似如下方案:

  

  我们可以赋予用户设计水印的能力,并为他们选择的图片添加水印。这不是更有趣吗?

  5. 总结

  上述教程的作者已经集成到H5-Dooring中。对于一些比较复杂的交互功能,也可以通过合理的设计来实现,大家可以自行探索研究。

  github地址:H5在线编辑器H5-Dooring

  最后

  如果想学习更多的前端知识和实战如H5游戏、webpack、node、gulp、css3、javascript、nodeJS、canvas数据可视化等,欢迎大家在“趣前端- end”,一起探索前端的边界。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线