htmlbutton提交form(html按钮提交表单)

  目录

  demo1 form表单,原生的上传文件

  demo2 plupload的原理

  demo3 moxie文件选取和文件预览

  demo4 moxie文件上传,进度提示

  demo5 使用plupload实现了图片上传

  demo6 断点续传

  demo7 plupload ui widget的示例

  本教程包含7个 demo ,它们循序渐进、由浅入深地讲解文件上传。每个 demo 都被精心设计,且都是可执行的。 因为我刚做完并上线了一个真实的文件上传程序,所以有些 demo 对实际生产有指导意义。

  除了前端的上传部分。后端的接收部分也由我们一手操办,并且没有用现成的包而是亲自去解析数据,因为我想让你更清晰的看到http协议。

  在运行 demo 的时候,请将网络速度调低,这样,我们就可以清楚的看到http的交互过程。 调低网络速度的方法之一,是用 chrome 的 debugger 工具,下文会有详细的图示。

  

  然后在浏览器中(建议 chrome )打开 https://localhost

  ERROR: 如果你遇到 EADDRINUSE 的错误,那是因为80端口已经被其它诸如apache 、nginx 的进程占用了。 可以在启动的时候指定端口, 比如端口 3000。

  $ node demo1/server.js 3000

  ERROR: 如果遇到EACCES的错误,请用sudo权限运行它。

  $ sudo node demo1/server.js

  1、form表单,原生的上传文件

  首先,来看第一个例子。 它是一个原生的文件提交方法,前端只有一段 html 而没有 js 。我们的目的是观察 http 协议的格式。

  前端 index.html,使用一个 input 标签进行文件选择,然后使用 form 表单发送数据。 后端 server.js,对表单发过来的数据进行解析,并用便于观察的方式打印出来。

  点击 “选择文件” 后

  在点击 Upload 按钮之前,对网络进行限速,方便观察数据传输的过程。打开debugger

  点击后,选取一个较慢的

  服务端会打印下面的提示,注意红框中的 token,它用来表示二进制数据的边界。

  你在 server.js 中可以看到解析 http 数据的 formidable 函数。 你可以调试它,用来学习 http 协议。

  上传完成后

  TIP: 观察,它是我们本次学习之旅的主要方法。你一定要运行每个例子,亲眼看到它们的结果。 它们发生了、产生了结果,你眼见为实、反复的确认后,就熟悉了这个技术。

  2、plupload的原理

  plupload是一个文件上传的前端插件。

  它的主页 https://www.plupload.com/

  它的github地址 https://github.com/moxiecode/plupload

  demo2并没有使用 plupload,事实上它是自己实现了 plupload,它本身就相当于plupload的v0.01版本。

  通过v0.01,这20行代码来一窥 plupload的原理。而不是去读 plupload的上万行代码, 真是有种两岸猿声啼不住,轻舟已过万重山的感觉呀。

  plupload的原理,就是拿到文件句柄后,自己发送 () 文件。 尽量控制整个过程,从中加入自己实现的功能,这就是它的想法。

比如,图片预览,是在拿到文件以后在新的 canvas 上画出新的尺寸。

比如,断点续传,是在拿到文件以后 slice 文件,从断点处开始读取。

  这些操作,都有个前提,就是要拿到文件。否则,一切就无从谈起。

  3、mOxie文件选取和文件预览

  这个例子没有服务端,请直接用浏览器打开 demo3/index.html。然后选取图片,就可以看到预览。 这样避免你想当然的认为,预览是服务端辅助的。

  文件预览一般的做法是,先上传图片,然后从图片服务器上下载 thumbnail,这么做是有缺点的,预览要先上传才能看到(可能人们更喜欢先看到再决定要不要上传)。但是这里采用的做法不同,它在本地进行预览,但这势必会增加一些 cpu 的开销,因为预览的实质是进行了图片压缩,要么服务端压缩要么客户端压缩而已。

  实际生产中,采用哪一种做法,要看需求,或者看你方便的程度。如果需求中删除图片的概率较高,那就采用本地预览-也就是本例的做法。如果服务器能存储压缩后的 thumbnail,且压力不大,速度够快,那就用服务端预览。

  另外, 当你看到 mOxie 的时候,可能会觉得莫名其妙。是这样的

  打开 https://www.plupload.com/docs/

  文档的最后一段话如下

Low-level pollyfills (mOxie)

Plupload API

UI Widget

Queue Widget

  其实我写本文的初衷,是为了解释这四句话。 我跟你一样,一开始读不懂。

  这四句话的意思是 plupload有四个安装等级 - 初级,中级,高级,长级

初级,叫 moxie.min.js,插件大小77k到106k不等(神马鬼?为什么不等的原因参见 《编译 mOxie》 一节,https://github.com/ktont/java-file-upload/blob/master/docs/compile.md)。 其中提到的 pollyfills 应为polyfiles,是帮助老浏览器跟上 h5 步伐的插件,叫 “ h5 垫片 ”,用 js 提升老浏览器的 api,抹平浏览器间的差异。所以 mOxie 其实是个通用前端库。

中级,plupload.full.min.js,插件大小123k 。打开它看一下,发现它其实是moxie.min.js 和一个叫 plupload.min.js 的文件合并到一起而已。 所以plupload其实是在 mOxie 的基础上,封装了一下文件上传api,专业文件上传前端库。

高级,它依赖 jquery 137k jquery ui 282k plupload 123k plupload ui 30k 一共约600k的大小。帮助你实现 ui,叫 widget - 小组件。

长级,它和高级差不多,也是实现一套 ui。区别是ui是队列,前者的ui是块和列表。

  那么回过头,再来看这个例子。这个例子只是演示文件选择,它没有上传的功能。 只有文件选择功能的 mOxie插件的大小为77k,比正常功能要小30%。为什么呢?

  因为 mOxie是一个可以自定义的前端库,如果有些功能不需要,比如 silverlight,那么就可以不把它们编到目标中。 参见《编译 mOxie 》(https://github.com/ktont/java-file-upload/blob/master/docs/compile.md)

  那么 mOxie都做了什么呢,为甚么有77k这么大(大吗?)的体积。它提供文件预览功能、图片压缩功能、国际化支持(就是i18n)等。同时,上面也提到,它解决浏览器的兼容性问题。

  4、moxie文件上传,进度提示

  这个例子只使用 mOxie提供的功能,实现了文件上传。

htmlbutton提交form(html按钮提交表单)

  

  您会发现,本例中的 mOxie库比上一例多了4k,那是因为在编译的时候加入了 的支持。 所以 demo4 中的 moxie.min.js 就是 plupload 库能投入生产的最精简版本。参见《编译mOxie》 (https://github.com/ktont/java-file-upload/blob/master/docs/compile.md )

  您可以在这个 demo 的基础上实现自己的文件上传。相比 Plupload API,它更灵活,您可能更喜欢在这个层次上编写应用。当然,灵活性的对立面是复杂度,它们之间的平衡点因人而异。

  5、使用plupload实现了图片上传

  这个例子,比较实际一点,使用 Plupload API。Plupload API主要在mOxie上实现一套事件驱动的机制。

  同时,顺带演习上传的暂停和重传。为甚么在这里演习暂停和重传呢?

  为了区分下个例子 – 断点续传。断点续传是指,重启了电脑后断点续传。

  断点续传在上传大文件的场景下,很有用。 比如我上传一个电影,中间关闭了电脑,然后睡个觉。醒来后可以继续传。

  下一个例子演示断点续传。

  而本例的重传是说,不重启浏览器的前提下,重新传文件。它会从头再来,之前传的会丢弃。 实际场景中,用来重传图片这种小文件。 因为小文件一个封包或几个封包就发送完了,没必要断点续传,也没法儿“断”了。 大炮不适合打蚊子,因为蚊子小(我怎么这么啰嗦——)

  6、断点续传

  是时候请出你的硬盘女神啦!运行本程序需要一个大文件,而电影文件再合适不过了。

  选取文件后,并没有立即上传。而是去服务器询问上次传输的断点。 在本例中,服务端会返回一个50到100的随机值,它表示百分比,用来模拟实际情况中的上次的断点。

  例如,下面图片中,上次的断点是94%

  你可能会误认为服务器会从94%的地方把数据存起来,不是的, 它的意思是告诉客户端,请从文件94%的地方把剩下的数据发送过来。

  服务端的情况

  本例中使用的 块 大小是 1兆字节,这个配置在 index.html的19行

  上图中,两个绿色框之间是一次独立的 http 交互过程,它用来发送一个块。 本例中的文件一共4G多,会切成4千多个块。产生4千多次 http 交互来发送它们。 相比不分块而一次 http 发送完所有数据,这么做会有些网络性能损耗。但是不分块的缺点是非常明显的。

  如果真的不分块,单 http 发送所有数据。假设网络异常,服务端 hanging,客户端此时开启另一个链接 retry。 retry 首先询问服务端上次的断点,然后从该断点处继续发送。 之前 hanging 的链接可能已经 hang up,也可能没有,这取决于服务端的超时时间。

  此时,服务端就会面临一个尴尬的选择,必须关闭之前 hanging 的链接 。因为如果不关闭,网络中残留的数据可能继续写入文件,导致数据错乱。 服务端一般请求间是无法操作的,一个请求不能操作其它请求。

  虽然,实际上几乎不会出现上面的情况,但是它不严谨。并且, http 协议是一个应用层协议。http 协议在 application和 network transfer更靠近 application。大多数 http 服务器都会帮你做封包的拼解工作,而让你从网络层传输层解放出来。如果达不到这一点,http 的处理还是和 tcp 一样麻烦,那 http 就不应该存在。参考 http协议( https://www.w3.org/Protocols/rfc2616/rfc2616-sec1.html )

  然而,如果分块来传输,就不会遇到这个问题。如果链接 hang up。那么整个请求的数据统统丢弃,偏移仍然在当前块。

  话说回来,所以要把文件数据拆分成一个较小的单元来用 http 传输,并且

用块发送可以降低 token 冲突的概率。上传文件是使用一个随机 token 来标记数据边界(第一个绿框)的。 当文件大的时候,会有可能遇到和 token 一样的字符串。但是,分块传,会每次都换一个 token。

适当的块大小,有助于浏览器读取文件。比如本例中 chrome 用的是 slice 读取文件,我们不能指望它很智能,塞给它一个很大的文件,让它很好的处理。有些浏览器对文件大小有限制,甚至在传大文件的时候会卡死。

  上图中,红色的框表示当前传输的是第几块数据。因为服务端给了随机值94%,所以这里是4261的尾部 -- 4005。

  黄色的框表示一共有多少块数据。当红色和黄色相等的时候,表示文件传输完成。

  灰色的框表示传输的二进制数据,数据的边界由第一个绿框定义。这个时候,这次 http 交互就完成了,链接会被关闭。紧接着会是下一块数据,一个全新的 http 交互,token 也会是一个新的。

  断点续传的关键在于 --从文件的指定偏移处读取(ZHUANGBI: c语言中 fseek)

  但是浏览器提供给前端的功能都是受限的,没有 fseek,而是提供了一个 slice功能。 比如,slice(off, off+1024)用来读取 off 处的1024字节数据。 还能凑合着用吧,那我们每次读一块数据,然后发送,再读下一块,再发送。。。

  突然发现,这不就是失传已久的 socket 编程吗?搞一个 缓冲,撸一串数据然后发出去,再撸一串数据再发出去。

  好吧!幸亏不是让我们写这种恶心的数据解析工作,plupload已经给我们写好了,我刚撸起的袖管赶紧放了下去。

  7、plupload ui widget的示例

  这个例子,用来展示 plupload 的 UI Widget。

  

  在index.html中,ui部分只需安置一个div

  plupload会在这个div中,自动安插一个ui组件,就是图片中展示的那个。

  这样极大的方便了开发,你可能一句 js 都没写,就实现了复杂的图片上传。 当然,你可以定制这个组件,那样需要一些学习成本,并且挺高的。所以,如果你想要一个轻量,自定义的 ui 组件的时候,就需要自己设计 ui了。 比如下面这样的

  在上面这个组件中,要求

最多只能选n张

更好的用户体验

可以删除节点

上传失败后可以重传

页面大小控制在100k以内

总结

  在生活中,图片上传的应用越来越广泛。特别是在智能手机普及以后,获得图片是很便捷的,图片的质量也很高。

  比如,在一个突发事件中,人们很及时的就能从各个角度拍到它,然后上传到互联网上或者分享到朋友圈。

  在移动端的开发中,因为手机的特点,它处理能力弱、展示空间小,导致图片上传技术有些困难。另外,站在运营商角度,从长远来看,手机流量会是主要的营收服务。虽然流量成本不高,但它不会便宜。这样,用户就会在乎自己的流量。还有,在实际应用中,需要后端配合搭建图片服务器、图片数据库,前端还要解决跨域的问题,虽然本文没讲这些,但实际也要开发者解决。所以,编写一个省流量的图片上传程序是一个挑战。

  另一方面,随着浏览器和web技术的持续推进。传统的大文件上传,势必会转到web上来实现,而不是一些桌面app。这里面甚至还蕴含一些商机。这还需要一些时间,因为我知道很多人还在用xp,但趋势很明确的。

  (文章所有内容已经发布在Github,本文页面点击【阅读原文】查看)


【免责声明】:

本站所发布的一切资源仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。

【关于转载】:

本站尊重互联网版权体系,本站部分图片、文章大部分转载于互联网、所有内容不代表本站观点、不对文章中的任何观点负责、转载的目的只用于给网民提供信息阅读,无任何商业用途,所有内容版权归原作者所有
如本站(文章、内容、图片、视频)任何资料有侵权,先说声抱歉;麻烦您请联系请后台提交工单,我们会立即删除、维护您的权益。非常感谢您的理解。

【附】:

二○○二年一月一日《计算机软件保护条例》第十七条规定:为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬!鉴于此,也希望大家按此说明研究软件!

注:本站资源来自网络转载,版权归原作者和公司所有,如果有侵犯到您的权益,请第一时间联系我们处理!

-----------------------------------------------------------------------------------------------------------

【版权声明】:

一、本站致力于为源码爱好者提供国内外软件开发技术和软件共享,着力为用户提供优资资源。
二、本站提供的源码下载文件为网络共享资源,请于下载后的24小时内删除。如需体验更多乐趣,还请支持正版。
三、如有内容侵犯您的版权或其他利益的,请编辑邮件并加以说明发送到站长邮箱。站长会进行审查之后,情况属实的会在三个工作日内为您删除。
-----------------------------------------------------------------------------------------------------------


内容投诉
源码村资源网 » htmlbutton提交form(html按钮提交表单)

1 评论

您需要 登录账户 后才能发表评论

发表评论

欢迎 访客 发表评论