转自 http://mp.weixin.qq.com/s?__biz=MzI2NzExNTczMw==&mid=2653284851&idx=1&sn=9967ae75e786890d438ebbd152c0fcd5

tags: 图片上传, multipart, 截图上传, file对象, FormData, 拖拽上传图片, dataTransfer, readAsDataURL

一个如下所示的发布框,经常会出现在各种微博、社区、论坛站点上,这类发布形式虽然没有高级编辑器那样可以任意排版加工,但也满足了常见的表述观点意见的要求,它通常搭配一些表情、文件上传、分享网页视频等方式,来满足上述需求。最近我从事的一个项目中,就完成了如下图示的发布内容的需求,今天主要讲一下其中图片和附件的上传发布方式。

其实上传的方式有很多种,本文将列举需求中用到的几种上传方式。

1. 表单上传

也就是用传统的form表单来上传,使用form表单的input[type=”file”]控件,可以打开系统的文件选择对话框,从而达到选择文件并上传的目的,它的好处是多浏览器兼容,但是在多图上传、分段上传上等高级特性上就显得力不从心。

表单的格式如下:

我列出表单上传所需的关键几点:

  • method=”post”: 采用post方式提交数据

  • enctype=”multipart/form-data”:采用multipart格式上传文件,此时request头会显示 Content-Type:multipart/form-data; boundary=——WebKitFormBoundaryzr34cwJ67R95KQC9

  • action:标明上传的服务端处理地址

  • type=”file”:使用input的file控件上传

  • accept属性是HTML5的新属性,它规定了可通过文件上传提交的文件类型

  • 上传的触发事件可以是:input[type=”file”]的onChange触发,也可以由一个独立的按钮的onClick使整个表单提交,此时还可以用input[type=”hidden”]带一些其它的参数,比如Token来源验证等等。

2. Ajax无刷新上传

ajax无刷新上传的方式,本质上与表单上传无异,只是把表单里的内容提出来采用ajax提交,并且由前端决定请求结果回传后的展示结果,不用像直接表单上传那样刷新和跳转页面。在这里,我们采用jQuery来作为操作DOM和创建ajax提交的js基础库。

html代码片段如下:

javascript代码片段如下:

我们使用了file控件的change来触发上传事件,当然你也可以使用某个按钮来触发表单提交。提交数据时,我用到了FormData对象来发送二进制文件,FormData构造函数提供的append()方法,除了直接添加二进制文件还可以附带一些其它的参数,作为XMLHttpRequest实例的参数提交给服务端。

如下是Firefox MDN对FormData的解释。

XMLHttpRequest Level 2添加了一个新的接口FormData.利用FormData对象,我们可以通过JavaScript用一些键值对来模拟一系列表单控件,我们还可以使用XMLHttpRequest的send()方法来异步的提交这个”表单”.比起普通的ajax,使用FormData的最大优点就是我们可以异步上传一个二进制文件.
https://developer.mozilla.org/zh-CN/docs/Web/API/FormData

BTW: 使用jQuery提供的ajax方法来发送二进制文件,还需要附加两个参数:

  • processData: false  // 不要对data参数进行序列化处理,默认为true

  • contentType: false  // 不要设置Content-Type请求头,因为文件数据是以 multipart/form-data 来编码

3. flash上传

很多时候上传的需求都不是只局限于单图上传,而且需要显示上传进度、中断上传过程、大文件分段上传等等,这时传统的表单上传无法实现这些功能,于是产生了使用Flash上传的方式,它采用Flash作为一个中间代理层,代替客户端跟服务端通信,此外,它也对客户端的文件选择方面拥有更多的控制权,比input[type=”file”]要大得多。

在这里我使用了jQuery封装好的uploadify插件来进行演示,一般这类插件都自带了上传用的Flash文件,因为跟服务端回传的数据和展示跟客户端的交互,都是Flash文件的接口跟插件来对接的。

<div id="file_upload">

html部分很简单,预留一个hook后,插件会在这个节点内部创建Flash的object,并且还附带创建了上传进度、取消控件和多文件队列展示等界面。


选择一个文件后,html代码如下所示:

更多的API和配置请参考jQuery.uploadify 官网APIs ( http://www.uploadify.com/documentation/ )
美中不足的是,mac下会对Flash有各种各样的限制,甚至不支持,所以使用的时候也要慎重考虑。

4. 截图粘贴上传

目前只有较大的几家SNS和微博类型的站点发布框实现了这个功能,本着业界良心和用户至上的原则,我们也在内外站点开发的早期上线了此功能,此次只是对上传接口的改造,在这里简单的把上传过程和用到的内容介绍一下。

首先,截图粘贴上传的核心思想是,监听粘贴事件,然后获取剪切板中的数据,如果是一张图片,则触发上传事件。
代码片段如下:


从上面代码可以看出,上传的过程都是一样的,主要是获取文件的方式。
当进行粘贴(右键paste/ctrl+v)操作时,触发剪贴板事件’paste’,从系统剪切板获取内容,而系统剪切板的数据在不同浏览器保存在不同的位置:

  • IE内核:windows.clipboardData

  • 其它:e.originalEvent.clipboardData

https://www.w3.org/TR/clipboard-apis/

5. 拖拽上传

拖拽上传的方式,支持的浏览器比较少,因为它用到了HTML5的两个新的属性(API)一个是Drag and Drop ( http://caniuse.com/#search=drag ),一个是File API ( http://caniuse.com/#search=file )

上传域监听拖拽的三个事件:dragEnter、dragOver和drop,分别对应拖拽至、拖拽时和释放三个操作的处理机制,当然你也可以监听dragLeave事件。

HTML5的File API提供了一个FileList的接口,它可以通过拖拽事件的e.dataTransfer.files来传递的文件信息,获取本地文件列表信息。

File API在HTML5规范中只是草案,在 W3C 草案中,File 对象只包含文件名、文件类型和文件大小等只读属性。但部分浏览器在草案之外提供了一个名为 FileReader 的对象,用以读取文件内容,并且可以监控读取状态,它提供的方法有: “readAsBinaryString” ,”readAsDataURL” ,”readAsText” ,”abort” 等。

参考MDN https://developer.mozilla.org/en-US/docs/Web/API/File

代码片段如下:

拖拽上传过程中的几个关键点:

  • 在drop事件触发后通过e.dataTransfer.files获取拖拽文件列表,在jQuery中是e.originalEvent.dataTransfer.files

  • 拖拽上传仅支持图片,文件对象中file.type标识了文件类型

  • 由于可能是多图拖拽,所以可以遍历图片上传,这里用了Underscore的each方法

  • 这里用readAsDataURL读取文件内容为二进制文件,你还可以将其转换为Base64方式上传,只是http协议里面存在对非二进制数据的上传大小限制为2M。

  • 上传的过程跟前面的方式相同,即:创建FormData对象并发起Ajax请求

总结

  1. 以上各种方式分别试用不同的场景,并无高下之分。

  2. 后面集中方式只有高级浏览器才支持,所以仅算是体验上的增强。

  3. 上面的代码仅是核心代码片段,如需运行还需补充参数,比如上传地址,当然,也需要服务器的支持。代码地址 ( https://github.com/moxiaohe/moxiaohe.github.io/issues/7 )

  4. 对于这些方式,阿里巴巴信息平台的uxcore框架已经封装了成型的组件且用在了我们日常的项目中,欢迎使用。传送门 uxcore-uploader ( http://uxco.re/components/uploader/ )

使用多种姿势上传图片相关推荐

  1. 变身吧,无人机:多种姿势可以选择,你喜欢X还是O?

    车栗子 发自 凹非寺  量子位 报道 | 公众号 QbitAI 一只无人机,为什么要学会变形呢? 来到一个窄小的洞口,把自己变瘦就可以飞进去了. 里面的天地宽广了,不需要畏手畏脚了,再把四肢舒展开来. ...

  2. Exploit编写教程2:跳转的多种姿势

    本文为 Exploit编写教程 的学习笔记,原文请点击这里 本文仅作以防御为目的的技术总结,所有操作均在实验环境下进行,请勿用于非法行为,否则后果自负. 如有侵权烦请告知,我们会立即删除并致歉.谢谢. ...

  3. C# Redis 分布式锁 续集 (新增Mysql分布式锁[还有更多种姿势])

    上个文章 <.Net Redis 实现分布式锁 >发出去之后,有很多大佬就有了自己的见解,让我获益良多,又学到了一些新姿势(知识). 上篇主要是采用了 StackExchange.Redi ...

  4. c++层次遍历_动画:二叉树遍历的多种姿势

    前言 在<什么是二叉树>中,我们介绍了二叉树的创建(插入),查找和删除,本文将介绍二叉树的遍历.而二叉树遍历有多种形式,他们也可以应用在不同的场景中,常见的深度优先遍历方式有前序遍历,中序 ...

  5. Django 使用定时任务的多种姿势对比

    写在前面: 最近由于工作原因,不得不使用 Windows 系统进行 Django 开发工作,然后原来使用的django-crontab插件没办法在Windows系统上面进行定时任务.因此又想了其他方式 ...

  6. tomcat后台多种姿势getshell

    目录 前提条件 用户权限介绍 GET SHELL war包部署上传 msf host-manager 模拟环境介绍 环境搭建 漏洞利用 JMX getshell 简介 环境搭建 JMX访问日志包含恶意 ...

  7. 使用姿势估计进行跌倒检测

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 所有目标检测已成为动作识别研究的重要垫脚石,即训练AI对行走和坐下 ...

  8. 【❌❌N种姿势满足你遍历C++ vector⭕⭕】C++ vector 遍历

    C++ vector遍历demo,多种姿势任你选~ 1.迭代器 for(vector<int>::iterator it = obj.begin(); it != obj.end(); i ...

  9. 用不同的姿势求逆序对(复习篇)

    用不同的姿势求逆序对(复习篇) 文章目录 用不同的姿势求逆序对(复习篇) 前言 讲解 归并排序 树状数组 线段树 题目 思路 代码 归并排序求逆序对 树状数组求逆序对 线段树求逆序对 历届试题 小朋友 ...

最新文章

  1. python太阳花的编程_python大佬养成计划----HTML DOM
  2. @ConditionalOnProperty 详解
  3. linux 服务器 iptables 防止arp病毒,让Linux系统有效防御ARP攻击的实用技巧
  4. getprocaddress得到为0_拼接图像得到全景图
  5. WinCE中中断的处理过程(驱动开发人员角度)
  6. python实现进程通信_python进程间的通讯实现
  7. 【转载】我只是随便说说的即时通讯
  8. HTML disabled
  9. 年轻人逃离大城市之后的下一站选哪儿?用数据来为你揭晓
  10. 盘点2019年5G:商用大戏开唱 三大问题亟待解决
  11. 100个灯泡python编程_算法题:一个圆环上有100个灯泡,灯泡有打...
  12. 华景机器人怎么控制_【扫地机器人选购】支持华为hilink智能家居联动/支持华为小艺语音控制的扫地机器人...
  13. JavaScript数据结构——图(Graph)
  14. type python django models_Django 模型
  15. CentOS6.5 环境安装配置
  16. windows通过注册表修改IP
  17. Scrapy 爬取今日头条街拍图片
  18. bilibili_api,仅用 3 行代码获取B站(弹幕、评论、用户)数据
  19. DAVINCI和OMAP架构的区别
  20. 自动聚焦技术(AF)

热门文章

  1. python怎么写lnx_如何在PYTHON程式中使用YOLO
  2. 双系统双硬盘的linux引导,双硬盘双系统Grub引导的配置
  3. android studio 下拉菜单,android studio 的下拉菜单Spinner使用详解
  4. 十二个“一”的文艺创作拓展:关于星座
  5. 华为2021软件精英挑战赛复赛赛后方案分享
  6. 全新2022测算系统完整版+支持对接结
  7. 操作系统教程第六版——第三章课后作业
  8. UE5学习笔记(二)——3D材质蓝图的常用节点介绍
  9. onlyoffice文档服务器安装,CentOS7部署OnlyOffice在线办公服务器
  10. js 跨域下载图片解决方法