热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

无刷新上传图片可以实时预览选择图片后即自动上传_基于业务场景下的图片/文件上传方案总结...

精彩回顾如何实现H5可视化编辑器的实时预览和真机扫码预览功能在线IDE开发入门之从零实现一个在线代码编辑器基于ReactKoa实现一个h5页面可视化编辑器-Doori
e1d464eb4e4df5f417ac07cbffaf22dc.png

精彩回顾

  • 如何实现H5可视化编辑器的实时预览和真机扫码预览功能
  • 在线IDE开发入门之从零实现一个在线代码编辑器
  • 基于React+Koa实现一个h5页面可视化编辑器-Dooring
  • TS核心知识点总结及项目实战案例分析

前言

图片/文件上传组是企业项目开发中必不可少的环节之一, 但凡涉及到用户模块的都会有图片/文件上传需求, 在很多第三方组件库(ant desigin, element ui)中它也是基础组件之一. 接下来笔者就来带大家从零实现一款图片/文件上传组件以及扩展出更强大的上传组件.

你将收获

  • 常用的图片上传功能实现方案
  • 手写一个图片/文件上传组件
  • 如何将裁剪功能集成到上传组件中
  • 内容平台/可视化平台下的图片自治方案
  • 如何扩展出更强大的图片上传方案

正文

作为一名前端工程师, 解决项目问题是我们的基本职责之一, 我们可以利用已掌握的知识去解决项目开发中的问题和需求, 这也是我们职业生涯必将经历的第一个阶段,即——适应期. 如果我们想继续晋升, 我们就需要不断的打怪升级,掌握各种技能, 这样我们才能在未来遇到问题时采用最佳的方案高效的解决问题, 也就是第二个阶段——发展期.

为了更快的进入发展期, 我们需要不断的提升自己的技术深度和广度, 能纵向考虑到问题的本质也能横向的对问题提出多种解决方案, 最终选择一种最优方案来实现. 要实现这一点,我们需要对问题做深度思考和复盘, 接下来笔者将介绍几种常用的图片上传方案,来扩展大家的广度.

1. 常用的图片上传方案

从web1.0时代开始, 我们用的最多的上传方案就是form表单, 我们只需要在form内写好各种input(输入型元素), 并定义好上传的服务器地址(action)即可.形式类似如下:

action="/xuxiaoxi/form/post">

class="form-item">type="text" />
class="form-item">type="passward" />
class="form-item">type="file" />
class="form-item">type="submit" />

在XHR技术还没普及时, 我们大多会选择上述方案, 唯一的缺点就是提交之后会刷新页面, 用户体验不太好, 还可能造成局部数据丢失, 但仍然有解决方案, 就是form + iframe技术.

1.1 form + iframe方案

form + iframe方案的基本思路就是我们提交动作是在父页面触发, 但是form表单指向为iframe, 这样可以实现局部刷新, 现在有些场景仍然在使用该方案, 具体原理如下:

41dbb9c7ccb36ebcf7d7c5582c60e002.png

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

1.2 ajax + formData方案

在XHR盛行之后,我们可以轻松使用ajax来实现异步请求了, 对于文件上传, 我们也可以更灵活的使用ajax和formData来实现, 逐渐脱离了对原生form表单的依赖.

FormData 对象用以将数据编译成键值对,以便用XMLHttpRequest来发送数据。其主要用于发送表单数据,但亦可用于发送带键数据(keyed data),而独立于表单使用。如果表单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的方式上传给了服务器, 是不是很简单呢? 笔者之前的文章 基于react/vue开发一个专属于程序员的朋友圈应用就采用了该方案, 感兴趣的可以学习研究一下.

如果要实现多文件上传也非常简单, 这里我们以axios为例, 具体实现如下:

const formData = new FormData()for(let i=0; i formData.append(`file_${i+1}`, files[i].file)
}
axios({
method: 'post',
url: '/files/upload/tx',
data: formData,
headers: {'Content-Type': 'multipart/form-data'
}
});

 这里要注意多文件上传要在请求的http header中设置 Content-Type 为 multipart/form-data . 当然大家还可以基于以上原理实现更符合自身业务需求的文件上传组件, 比如预览, 限流等.

1.3 第三方组件实现

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

  • antd/element 的 upload 组件
  • FilePond 可以上传任何内容,并能够优化图像以加快上传速度,同时提供顺畅的用户体验
  • Web Uploader 百度WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件
  • vue-simple-uploader 基于vue的强大美观的文件上传组件
我们可以通过上述提供的第三方组件库, 结合自己服务端的配置,就可以轻松实现强大的上传组件了.

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

对于图片上传组件来说, 我们往往不能确定用户上传的到底是什么, 所以我们要提前约束, 比如说对图片大小, 图片格式, 图片比例等进行限制以符合我们的业务标准. 图片大小和图片格式的限制非常好实现, 但是对于图片比例, 这个我们不能期望用户自己来处理, 因为这样会极大的增加用户使用网站的负担, 所以我们可以提供一种功能, 让用户在线切图. 如下图所示:

017404957dffbdb9a17ccbdf259959b2.png以上截图来自于H5-Dooring在线编辑器的图片上传组件, 在用户上传之后我们会出现图片裁切界面, 我们会指定图片的比例, 让用户自由裁切. 笔者将基于antd的upload组件配合antd-img-crop来带大家实现在线切图功能. 具体代码实现如下:

import React, { useState } from 'react';import { Upload } from 'antd';import ImgCrop from 'antd-img-crop';const Demo = () => {const [fileList, setFileList] = useState([
{
uid: '-1',
name: 'image.png',
status: 'done',
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
},
]);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 (rotate> action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
listType="picture-card"
fileList={fileList}
onChange={onChange}
onPreview={onPreview}
>
{fileList.length <5 && &#39;&#43; Upload&#39;}
);
};
ReactDOM.render(, mountNode);

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

f911224015f0cc134ed3464f71b1c968.png

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

对于内容平台或者可视化平台而且, 单纯的上传图片还不能满足用户的需求, 因为内容/可视化平台更加注重图片的选择和使用, 对图片要求也很高, 用户自己上传毕竟资源有限, 往往不能达到用户对内容发布的需求或者可视化设计的需求, 所以往往在这类平台中会提供图片素材库这一功能, 用户可以在素材库中搜索海量图片以满足自己的需求, 而往往这样, 才更能留住用户, 增加用户粘性.

基于以上场景产品经理往往会提出这样的需求: 能不能提供可选方案, 用户既能自己上传图片, 也能使用我们提供的图片库资源呢? 这个时候有经验的前端往往会说一句: 安排!

在设计该功能之前我们往往要先参考其他已有实现, 这里我们举几个例子, 如下图所示:

177d1f178c38a1cfc8c01a596b90fda8.png0197301fbc70388c2616db6beefba5f4.pngbba3a430fdf0fc0d6728abf3f6ea3f99.png

以上案例中我们可以发现在用户上传图片的时候都会提供两个可选选项, 一个是本地上传, 一个是直接在图片库中选择, 所以我们的方案也类似, 可以统一将图片库封装到文件上传组件中作为通用功能, 也可以组合式封装, 各自可以独立使用也可以组合使用.

对于H5-Dooring对图片库的封装, 使用了将其作为通用服务来实现, 也就是但凡使用了上传组件,一定会出现可选的从图片库选择按钮. 实现方案也很简单, 就是在upload组件中扩展一层, 使用Modal&#43;Tab来做图片选择的界面, 当选择完成后将图片的地址手动设置到upload组件中即可. 代码如下:

handleImgSelected&#61; () &#61;> {const fileList &#61; [
{
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的form组件的受控模式.

4. 图片上传组件扩展

上面介绍的方案对于基本使用场景完全够用了, 但是如果是内容网站或者可视化搭建平台, 由于我们的配置可能会随时分发到公网, 这就会涉及到内容安全的问题, 如果一旦用户配置了违法的图片信息, 那么对于平台提供上可能会受到牵连, 所以我们还需要提供一套完善的审核机制, 比如用户配置好或者发布好内容后, 需要进过审核才能正式发布到线上, 但是完全依赖人工审核效率又比较低, 所以这个时候我们就需求找到机器自动化审核方案了. 比如阿里云和腾讯云等都提供了图片鉴别等服务, 我们可以将这些服务集成到我们的组件中, 来实现真正的业务自治能力, 这样才能更安全的进行企业化经营和开发.

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

d5be883956f045afc5fcd483c4d0a34b.png

我们能让用户有能力对自己选择的图片进行自行设计, 加水印等能力, 这样是不是更有意思呢?

5. 总结

以上教程笔者已经集成到H5-Dooring中&#xff0c;对于一些更复杂的交互功能&#xff0c;通过合理的设计也是可以实现的&#xff0c;大家可以自行探索研究。github?&#xff1a;h5-Dooring

最后

如果想学习更多H5游戏, webpack&#xff0c;node&#xff0c;gulp&#xff0c;css3&#xff0c;Javascript&#xff0c;nodeJS&#xff0c;canvas数据可视化等前端知识和实战&#xff0c;欢迎在《趣谈前端》一起学习讨论&#xff0c;共同探索前端的边界。

05db8f8e22e2b09cd5f8c0379b094d2c.png

评论区




推荐阅读
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了使用AJAX的POST请求实现数据修改功能的方法。通过ajax-post技术,可以实现在输入某个id后,通过ajax技术调用post.jsp修改具有该id记录的姓名的值。文章还提到了AJAX的概念和作用,以及使用async参数和open()方法的注意事项。同时强调了不推荐使用async=false的情况,并解释了JavaScript等待服务器响应的机制。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 本文讲述了如何通过代码在Android中更改Recycler视图项的背景颜色。通过在onBindViewHolder方法中设置条件判断,可以实现根据条件改变背景颜色的效果。同时,还介绍了如何修改底部边框颜色以及提供了RecyclerView Fragment layout.xml和项目布局文件的示例代码。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文讨论了在Spring 3.1中,数据源未能自动连接到@Configuration类的错误原因,并提供了解决方法。作者发现了错误的原因,并在代码中手动定义了PersistenceAnnotationBeanPostProcessor。作者删除了该定义后,问题得到解决。此外,作者还指出了默认的PersistenceAnnotationBeanPostProcessor的注册方式,并提供了自定义该bean定义的方法。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • HDFS2.x新特性
    一、集群间数据拷贝scp实现两个远程主机之间的文件复制scp-rhello.txtroothadoop103:useratguiguhello.txt推pushscp-rr ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • Python SQLAlchemy库的使用方法详解
    本文详细介绍了Python中使用SQLAlchemy库的方法。首先对SQLAlchemy进行了简介,包括其定义、适用的数据库类型等。然后讨论了SQLAlchemy提供的两种主要使用模式,即SQL表达式语言和ORM。针对不同的需求,给出了选择哪种模式的建议。最后,介绍了连接数据库的方法,包括创建SQLAlchemy引擎和执行SQL语句的接口。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
author-avatar
拍友2502940513
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有