亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

web開發之文件上傳的實現方式有哪些

發布時間:2022-04-18 16:01:38 來源:億速云 閱讀:139 作者:iii 欄目:開發技術

這篇文章主要介紹了web開發之文件上傳的實現方式有哪些的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇web開發之文件上傳的實現方式有哪些文章都會有所收獲,下面我們一起來看看吧。

文件上傳是 Web 開發常見需求,上傳文件需要用到文件輸入框,如果給文件輸入框添加一個 multiple 屬性則可以一次選擇多個文件(不支持的瀏覽器會自動忽略這個屬性)

<input multiple type="file">

點擊這個輸入框就可以打開瀏覽文件對話框選擇文件了,一般一個輸入框上傳一個文件就行,要上傳多個文件也可以用多個輸入框來處理,這樣做是為了兼容那些不支持 multiple 屬性的瀏覽器,同時用戶一般也不會選擇多個文件

基本上傳方式

當把文件輸入框放入表單中,提交表單的時候即可將選中的文件一起提交上傳到服務器,需要注意的是由于提交的表單中包含文件,因此要修改一下表單元素的 enctype 屬性為 multipart/form-data

<form action="#" enctype="multipart/form-data" method="post">  <input name="file" type="file">  <button type="submit">Upload</button></form>

這樣上傳方式是傳統的同步上傳,上傳的文件如果很大,往往需要等待很久,上傳完成后頁面還會重新加載,并且必須等待上傳完成后才能繼續操作

早期的瀏覽器并不支持異步上傳,不過可以使用 iframe 來模擬,在頁面中隱藏一個 <iframe> 元素,指定一個 name 值,同時將 <form> 元素的 target 屬性值指定為 <iframe> 元素的 name 屬性的值,將兩者關聯起來

<form action="#" enctype="multipart/form-data" method="post" target="upload-frame">  <input name="file" type="file">  <button type="submit">Upload</button></form><iframe id="upload-frame" name="upload-frame" src="about:blank" style="display: none;"></iframe>

這樣在提交表單上傳的時候,頁面就不會重新加載了,取而代之的是 iframe 重新加載了,不過 iframe 原本就是隱藏的,即使重新加載也不會感知到

訪問文件

File API 提供了訪問文件的能力,通過輸入框的 files 屬性訪問,這會得到一個 FileList,這是一個集合,如果只選擇了一個文件,那么集合中的第一個元素就是這個文件

var input = document.querySelector('input[type="file"]')var file = input.files[0]console.log(file.name) // 文件名稱console.log(file.size) // 文件大小console.log(file.type) // 文件類型

支持 File API 的瀏覽器可以參考 caniuse

Ajax 上傳

由于可以通過 File API 直接訪問文件內容,再結合 XMLHttpRequest 對象直接將文件上傳,將其作為參數傳給 XMLHttpRequest 對象的 send 方法即可

var xhr = new XMLHttpRequest()xhr.open('POST', '/upload/url', true)xhr.send(file)

不過一些原因不建議直接這樣傳遞文件,而是使用 FormData 對象來包裝需要上傳的文件,FormData 是一個構造函數,使用的時候先 new 一個實例,然后通過實例的 append 方法向其中添加數據,直接把需要上傳的文件添加進去

var formData = new FormData()formData.append('file', file, file.name) // 第 3 個參數是文件名稱formData.append('username', 'Mary') // 還可以添加額外的參數

甚至也可以直接把表單元素作為實例化參數,這樣整個表單中的數據就全部包含進去了

var formData = new FormData(document.querySelector('form'))

數據準備好后,就是上傳了,同樣是作為參數傳給 XMLHttpRequest 對象的 send 方法

var xhr = new XMLHttpRequest()xhr.open('POST', '/upload/url', true)xhr.send(formData)

監測上傳進度

XMLHttpRequest 對象還提供了一個 progress 事件,基于這個事件可以知道上傳進度如何

var xhr = new XMLHttpRequest()xhr.open('POST', '/upload/url', true)xhr.upload.onprogress = progressHandler // 這個函數接下來定義

上傳的 progress 事件由 xhr.upload 對象觸發,在事件處理程序中使用這個事件對象的 loaded(已上傳字節數) 和 total(總數) 屬性來計算上傳的進度

function progressHandler(e) {  var percent = Math.round((e.loaded / e.total) * 100)}

上面的計算會得到一個表示完成百分比的數字,不過這兩個值也不一定總會有,保險一點先判斷一下事件對象的 lengthComputable 屬性

function progressHandler(e) {  if (e.lengthComputable) {    var percent = Math.round((e.loaded / e.total) * 100)  }}

支持 Ajax 上傳的瀏覽器可以參考 caniuse https://caniuse.com/#feat=xhr2

分割上傳

使用文件對象的 slice 方法可以分割文件,給該方法傳遞兩個參數,一個起始位置和一個結束位置,這會返回一個新的 Blob 對象,包含原文件從起始位置到結束位置的那一部分(文件 File 對象其實也是 Blob 對象,這可以通過 file instanceof Blob 確定,Blob 是 File 的父類)

var blob = file.slice(0, 1024) // 文件從字節位置 0 到字節位置 1024 那 1KB

將文件分割成幾個 Blob 對象分別上傳就能實現將大文件分割上傳

function upload(file) {  let formData = new FormData()  formData.append('file', file)  let xhr = new XMLHttpRequest()  xhr.open('POST', '/upload/url', true)  xhr.send(formData)}var blob = file.slice(0, 1024)upload(blob) // 上傳第一部分var blob2 = file.slice(1024, 2048)upload(blob2) // 上傳第二部分// 上傳剩余部分

通常用一個循環來處理更方便

var pos = 0 // 起始位置var size = 1024 // 塊的大小while (pos < file.size) {  let blob = file.slice(pos, pos + size) // 結束位置 = 起始位置 + 塊大小  upload(blob)  pos += size // 下次從結束位置開始繼續分割}

服務器接收到分塊文件進行重新組裝的代碼就不在這里展示了

使用這種方式上傳文件會一次性發送多個 HTTP 請求,那么如何處理這種多個請求同時發送的情況呢?方法有很多,可以用 Promise 來處理,讓每次上傳都返回一個 promise 對象,然后用 Promise.all 方法來合并處理,Promise.all 方法接受一個數組作為參數,因此將每次上傳返回的 promise 對象放在一個數組中

var promises = []while (pos < file.size) {  let blob = file.slice(pos, pos + size)  promises.push(upload(blob)) // upload 應該返回一個 promise  pos += size}

同時改造一下 upload 函數使其返回一個 promise

function upload(file) {  return new Promise((resolve, reject) => {    let formData = new FormData()    formData.append('file', file)    let xhr = new XMLHttpRequest()    xhr.open('POST', '/upload/url', true)    xhr.onload = () => resolve(xhr.responseText)    xhr.onerror = () => reject(xhr.statusText)    xhr.send(formData)  })}

當一切完成后

Promise.all(promises).then((response) => {  console.log('Upload success!')}).catch((err) => {  console.log(err)})

支持文件分割的瀏覽器可以參考 caniuse

判斷一下文件對象是否有該方法就能知道瀏覽器是否支持該方法,對于早期的部分版本瀏覽器需要加上對應的瀏覽器廠商前綴

var slice = file.slice || file.webkitSlice || file.mozSliceif (slice) {  let blob = slice.call(file, 0, 1024) // call  upload(blob)} else {  upload(file) // 不支持分割就只能直接上傳整個文件了,或者提示文件過大}

拖拽上傳

通過拖拽 API 可以實現拖拽文件上傳,默認情況下,拖拽一個文件到瀏覽器中,瀏覽器會嘗試打開這個文件,要使用拖拽功能需要阻止這個默認行為

document.addEventListener('dragover', function(e) {  e.preventDefault()  e.stopPropagation()})

任意指定一個元素來作為釋放拖拽的區域,給一個元素綁定 drop 事件

var element = document.querySelector('label')element.addEventListener('drop', function(e) {  e.preventDefault()  e.stopPropagation()  // ...})

通過該事件對象的 dataTransfer 屬性獲取文件,然后上傳即可

var file = e.dataTransfer.files[0]upload(file) // upload 函數前面已經定義

選擇類型

給文件輸入框添加 accept 屬性即可指定選擇文件的類型,比如要選擇 png 格式的圖片,則指定其值為 image/png,如果要允許選擇所有類型的圖片,就是 image/*

<input accept="image/*" type="file">

添加 capture 屬性可以調用設備機能,比如 capture="camera" 可以調用相機拍照,不過這并不是一個標準屬性,不同設備實現方式也不一樣,需要注意

<input accept="image/*" capture="camera" type="file">

經測 iOS 設備添加該屬性后只能拍照而不能從相冊選擇文件了,所以判斷一下

if (iOS) { // iOS 用 navigator.userAgent 判斷  input.removeAttribute('capture')}

不支持的瀏覽器會自動忽略這些屬性

自定義樣式

文件輸入框在各個瀏覽器中呈現的樣子都不大相同,而且給 input 定義樣式也不是那么方便,如果有需要應用自定義樣式,有一個技巧,可以用一個 label 關聯到這個文件輸入框,當點擊這個 label 元素的時候就會觸發文件輸入框的點擊,打開瀏覽文件的對話框,相當于點擊了文件輸入框一樣的效果

<label for="file-input"></label><input id="file-input" style="clip: rect(0,0,0,0); position: absolute;" type="file">

這時就可以將原本的文件輸入框隱藏了,然后給 label 元素任意地應用樣式,畢竟要給 label 元素應用樣式比 input 方便得多

關于“web開發之文件上傳的實現方式有哪些”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“web開發之文件上傳的實現方式有哪些”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

罗定市| 淄博市| 侯马市| 会理县| 枝江市| 新密市| 伊宁市| 宣威市| 牟定县| 辉县市| 瑞丽市| 三门峡市| 澄迈县| 威宁| 达州市| 霞浦县| 昌黎县| 马边| 宿松县| 临漳县| 仁化县| 双辽市| 手机| 兴宁市| 高雄市| 应城市| 巴南区| 乐都县| 鸡东县| 海阳市| 剑河县| 泾阳县| 长阳| 灯塔市| 桂平市| 崇文区| 方山县| 吉林市| 铁岭县| 元氏县| 眉山市|