瀏覽器文件上傳淺淡

瀏覽器文件上傳淺淡

form 表單的各類格式

在出現 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

  1. GET 類請求

其內容是添加到 URL 的 query 部分的:前端

foo=bar&baz=The+first+line.%0D%0AThe+second+line.%0D%0A
  1. application/x-www-form-urlencoded

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
  1. multipart/form-data
    這種方式是支持傳輸其餘類型的數據,好比文件或者 blob 類型數據。
    其格式以下:
------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 type="file"/>

和其餘類型的 input 相同,事件都是比較相似的。獲取值的方式爲添加 change 事件便可。
除此以外,還支持幾個經常使用的屬性github

  • multiple 多選屬性,可進行多選
  • webkitdirectory 選擇文件夾功能,注意該屬性只支持 chrome 和 firefox
  • accept 設置選擇文件的類型,好比 'image/*', 支持圖片類型等

在 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

實現文件上傳

iframe + form

普通 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>

FormData

因爲 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

相關文章
相關標籤/搜索