在出现 ajax 以前,前端是使用 form 表单进行提交数据的,它的结构大概是这样:javascript
<form> <input type="text" name="username"/> <button type="submit">提交</button> </form>
在 form 表单进行提交时,则支持有四种方式(来自:https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Submitting_forms_and_uploading_files):
application/x-www-form-urlencoded
, text/plain
, multipart/form-data
, GET 方式即 URL 传参。html
其内容是添加到 URL 的 query 部分的:前端
foo=bar&baz=The+first+line.%0D%0AThe+second+line.%0D%0A
POST 方式进行传输与 GET 相似内容时,其数据可放在 body 内,application/x-www-form-urlencoded
方式内保证数据格式与普通的 GET 方式相似:java
Content-Type: application/x-www-form-urlencoded foo=bar&baz=The+first+line.%0D%0AThe+second+line.%0D%0A
------WebKitFormBoundaryKnsKCAS4s0kSeNQ3 Content-Disposition: form-data; name="外卖测试.png"; filename="Pictures/aa.png" Content-Type: image/png ------WebKitFormBoundaryKnsKCAS4s0kSeNQ3 Content-Disposition: form-data; name=".localized"; filename="Pictures/.localized" Content-Type: application/octet-stream ------WebKitFormBoundaryKnsKCAS4s0kSeNQ3 Content-Disposition: form-data; name="start.png"; filename="Pictures/start.png" Content-Type: image/png ------WebKitFormBoundaryKnsKCAS4s0kSeNQ3--
它的主要结构是以分界符进行分隔,每一个分界符后面带有 \r\n
,最后一个分界符会多个 --
,表示数据传输结束。
它在服务端的解析能够参考 https://blog.csdn.net/shmnh/article/details/49012417git
<input type="file"/>
和其余类型的 input 相同,事件都是比较相似的。获取值的方式为添加 change 事件便可。
除此以外,还支持几个经常使用的属性github
在 change 事件中,能够从 e.target.files
获取,它是个伪数组,可用 slice 转换为真正的数组。
内部结构大概以下:web
lastModified: 1519638407937, lastModifiedDate : Mon Feb 26 2018 17:46:47 GMT+0800 (CST) name: "aaa.png" size: 1222046 type: "image/png" webkitRelativePath: "Pictures/外卖测试.png"
这些参数都是比较有用的参数,利用它们能够实现各类复杂的功能。ajax
普通 form 实现其中有最大的问题是表单提交后,页面会进行跳转,为了解决这个问题,将 form 的 target 设置为一个隐藏的 iframe,
保证调用完成 submit 后仍旧可停留当前页面chrome
<form action="/api/upload" target="empty-iframe" enctype="multipart/form-data" method="POST"> <input name="file" type="file" multiple webkitdirectory="" /> <button type="submit">提交</button> </form> <iframe src="" name="empty-iframe" frameborder="0" style="width: 100%;min-height: 400px;"></iframe>
因为 IE10 后支持了 FormData 对象,这样咱们提交数据就很方便了。FormData 使用方法是:api
const xhr = new XMLHttpRequest() const form = new FormData() form.append(key, data) form.append(file.name, file.file) xhr.open('post', action, true) xhr.send(form)
实现起来就很简单了
在有些状况下,可能在上传要前展现本地的图片,因此咱们须要读取文件。通用的一种方法是使用 URL.createObjectURL,
固然,该方法仍是处于草案阶段,但浏览器已经基本支持了。它会生成了一个以 blob:// 开头的地址,指向一个浏览器建立的临时地址。
这样至关于直接网络读取。
对于一些小的图片也能够先进行读取后展现,好比咱们知道图片是支持 base64 的方式的,那么咱们就能够将图片转为 base64 方式进行读取。
以下例使用 FileReader 进行读取为 base64, 并进行 md5 校验:
const reader = new FileReader() reader.onload = function (e) { dataPicList.querySelector('#id-' + uid).src = e.target.result const spark = new SparkMD5() spark.append(e.target.result) const hexHash = spark.end() console.log(hexHash) } reader.readAsDataURL(file)
固然,对 base64 获取的 md5 会与二进制的不一样,同时对于大文件读取至内存再处理会有诸多问题,这些都是能够考虑的一个方向。
本文中实践的示例在:https://github.com/wenlonghuo/code-test/tree/master/005_upload