专栏首页艺述思维前端:选取、预览、裁剪、上传、断点续传,关于图片上传那点事

前端:选取、预览、裁剪、上传、断点续传,关于图片上传那点事

所有轮子都造好了已经~

目录


01

选择

直接上代码,原生的,非类库的:

<input type="file" accept=".jpg, .jpeg, .png" capture="user" multiple />

进入 Html5 时代,在页面中开启上传功能,只需要一个 input 组件。type 代表上传,accept 代表接受的文件类型,capture 代表从摄像头拍照获取,capture="user" 代表默认打开前置摄像头,multiple 代表一次可上传多个文件。

02

剪切板上传与拖拽上传

在可编辑区域开启contenteditable,为编辑区绑定paste事件,然后处理paste 事件,从 event.clipboardData || window.clipboardData 获得数据,接着将该数据转换为文件items[i].getAsFile()。拿到 File 后,与选取就是一样的处理逻辑了。

拖拽操作的实现是类似的。定义一个允许拖放文件的区域,通过 e.preventDefault() 为该区域取消drop 事件的默认行为。监听鼠标在拖拽区域上 的 dragover 及鼠标离开拖拽区域 dragleave 事件。在拖拽区域上释放文件发生 drop 事件时,通过 e.dataTransfer.files 获得文件信息。拿到 File 后,与前面处理逻辑一样。

03

预览

以前在页面上实现预览功能,要么将图片上传到服务器上,拿到 url 再拉回本地,赋值给 img 显示;要么使用 Flash 技术。

现在好了,可以直接使用 URL.createObjectURL 将 input[file] 选择的文件在用户本地转化为一个 可以赋值给 img 组件 src 属性的图片地址。

const $ = document.getElementById.bind(document);...$inputFile.addEventListener('change', function() {const file = this.files[0];  $previewImage.src = URL.createObjectURL(file);}, this);

这段代码看起来很简洁,$ 绑定在 document 对象上,不引入 JQuery 或 Zepto,也可以优雅地查找页面元素。使用 addEventListener 监听 input[file] 的 change 事件,当用户选择图片文件时,调用 URL.createObjectURL(file) 将 File 对象转化为可被 img 组件接受并预览的图片地址。

除了 使用 URL.createObjectURL,还可以使用 FileReader 。

const file = this.files[0];const reader = new FileReader();reader.addEventListener('load', function() {  $previewImage.src = reader.result;}, false);
if(file) {  reader.readAsDataURL(file);}

FileReader 是异步的,且只能加载安全沙箱之内的用户内容,它并不能像其它语言的 file 模块那样在用户的文件系统中按路径随意读取文件。

实现预览功能,直接使用 URL.createObjectURL 实现即可,更简洁。

04

裁剪

实现选取、裁剪图片部分区域的功能。直接使用下面这个库:

https://github.com/fengyuanchen/cropperjs

可定制,基本能满足所有需求;也可以基于 MIT 协议修改。

function showCropper() {$cropper.style.display = 'block';cropperInstance && cropperInstance.destroy();cropperInstance = new Cropper($cropperImage, {  viewMode: 1,  aspectRatio: 1,  autoCropArea: 1,  dragMode: 'move',  guides: false,  highlight: false,  cropBoxMovable: false,  cropBoxResizable: false});}

05

上传

使用 new FormData 可以直接构建表单数据对象,然后发送给服务器:

const formData = new FormData();formData.append('avatar', blob);fetch('server url', {  method: 'POST',  body: formData});

旧方式拼接 XMLHttpRequest 请求体的朝代已经一去不复返了:

06

断点续传

有时候文件比较大,或网络环境不稳定,需要实现分片上传及断点续传;有时候单纯为了追求上传速度,希望将浏览器 6 个并发连接跑满,所以也希望实现分片上传。

方案很简单。从 input[file] 选择拿到的对象是一个 File 对象,它继续于 Blob。Blob 对象表示一个不可变、原始数据的类文件对象,并且有一个 slice 方法,可以将自身分割为多个小段的 Blob 对象。每个小段 Blob 是可以单独发给服务器的。

let chunkSize=2*1024*1024;//分片大小 2Mlet file = document.getElementById('f1').files[0];if(file.size>chunkSize){let start=0,end=0;while (true) {        end += chunkSize;let blob = file.slice(start,end);        start+=chunkSize;        ...        chunks.push(blob);//保存分段数据    }}else{    chunks.push(file.slice(0));}

截段之后,还需要一个 js-spark-md5 类库:

https://github.com/satazor/js-spark-md5

这是一个在本地就可以给 Blog 对象签名生成唯一标识的类库,只要上传的是同一个文件,只要分段大小一致,网络断了再次上传,生成的标识也是一样的。每次上传完一个切片,就将标识存储在本地,页面刷新后先看看本地哪些分片已经上传过了。

— END —

2019 年冬天于北京


往期精选

JS是如何计算 1+1=2 的?

微信为什么要搞一个小游戏?

前端:浏览器、GPU 工作原理简要及动画编程启示

篆刻漫谈一二

本文分享自微信公众号 - 艺述思维(yishulun2005)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 使用rclone迁移FTP数据到COS

    与ftp配置一样,同样可以通过ftp config来配置cos,但我们也可以通过直接修改配置文件的方式来配置cos:

    ictfox
  • 你有快速备份和迁移 Kubernetes 集群应用以及持久化数据的需求吗,Velero 助你秒实现!

    Heptio Velero ( 以前的名字为 ARK) 是一款用于 Kubernetes 集群资源和持久存储卷(PV)的备份、迁移以及灾难恢复等的开源工具。

    iMike
  • 史上最强跨平台、多端加密同步神器,你有用过吗?

    Restic 是一款 GO 语言开发的开源免费且快速、高效和安全的跨平台备份工具。Restic 使用加密技术来保证你的数据安全性和完整性,可以将本地数据加密后传...

    iMike
  • Stack Overflow 上 370万浏览量的一个问题:如何比较 Java 的字符串?

    在逛 Stack Overflow 的时候,发现了一些访问量像喜马拉雅山一样高的问题,比如说这个:如何比较 Java 的字符串?访问量足足有 370万+,这不得...

    沉默王二
  • Redis选13亿个Key,4个field还是1亿个Key,13亿*4个field?

    哈希hash又称为散列、杂凑等,是将任意长度的输入通过散列算法变换为固定长度的输出,最终输出也就是哈希值。这种转换是一种压缩映射。也就是说,散列值的空间通常要远...

    王知无
  • 云集:一个没有理想的电商“印刷机”?

    双十一要来了! 在这个消费者“剁手”的日子,做精选、做拼团、做内容导购的电商们,纷纷下血本、搞噱头以期在这个节点爆发。从这几年双十一的火爆情况来看,能在这个“全...

    刘旷
  • Kernel PCA for nonlinear dimensionality reduction核心PCA非线性降维

    Most of the techniques in statistics are linear by nature, so in order to captur...

    到不了的都叫做远方
  • Java中Array与ArrayList的10个区别

    Array和ArrayList都是Java中两个重要的数据结构,在Java程序中经常使用。并且ArrayList在内部由Array支持,了解Java中的Arra...

    淡定的蜗牛
  • linux的wget命令

    Linux wget是一个下载文件的工具,它用在命令行下。对于Linux用户是必不可少的工具,尤其对于网络管理员,经常要下载一些软件或从远程服务器恢复备份到本地...

    于小勇
  • 1051 复数乘法 (15 分)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    韩旭051

扫码关注云+社区

领取腾讯云代金券