前端文件上傳

本文已整理到 Github,地址 ?? blog

如果我的內(nèi)容幫助到了您,歡迎點個 Star ?????? 鼓勵鼓勵 :) ~~

我希望我的內(nèi)容可以幫助你“懵耄現(xiàn)在我專注于前端領(lǐng)域迷殿,但我也將分享我在有限的時間內(nèi)看到和感受到的東西。


簡單文件上傳

文件上傳的傳統(tǒng)形式乍钻,是使用表單元素 file

<input type="file" id="file-uploader">

你可以添加 change 事件監(jiān)聽器讀取 event.target.files 文件對象肛循。

const fileUploader = document.getElementById('file-uploader')
fileUploader.addEventListener('change', (e) => {
  const files = e.target.files
  console.log('files', files)
})

多個文件上傳

使用 multiple 屬性

<input type="file" id="file-uploader" multiple />

文件元數(shù)據(jù)

在成功上傳文件內(nèi)容后铭腕,您可能需要顯示該文件內(nèi)容。對于圖片多糠,如果我們在上傳后不立即將上傳的圖片顯示給用戶累舷,則會感到困惑。

每當(dāng)上傳文件時夹孔,File 對象都會包含元數(shù)據(jù)信息被盈,如文件名稱、大小搭伤、上次更新時間只怎、類型等。此信息可用于進一步驗證和決策闷畸。

const fileUploader = document.getElementById('file-uploader')

// 偵聽更改事件并讀取元數(shù)據(jù)
fileUploader.addEventListener('change', (e) => {
  // 獲取文件列表數(shù)組
  const files = e.target.files

  // 循環(huán)瀏覽文件并獲取元數(shù)據(jù)
  for (const file of files) {
    const name = file.name
    const type = file.type ? file.type: 'NA'
    const size = file.size
    const lastModified = file.lastModified
    console.log({ file, name, type, size, lastModified })
  }
})

上傳前預(yù)覽圖像

我們準(zhǔn)備一個上傳文件控件尝盼,并為預(yù)覽所選文件準(zhǔn)備 img 元素,結(jié)構(gòu)如下:

<input type="file" id="fileInput" />

<img id="preview" />

getElementById() 方法可以獲取這兩個元素:

const fileEle = document.getElementById('fileInput')
const previewEle = document.getElementById('preview')

使用 URL.createObjectURL() 方法

URL.createObjectURL() 方法包含一個表示參數(shù)中給出的對象的 URL佑菩。這個新的 URL 對象表示指定的 File 對象或 Blob 對象盾沫。

fileEle.addEventListener('change', function (e) {
  // 獲取所選文件
  const file = e.target.files[0]

  // 創(chuàng)建引用該文件的新 URL
  const url = URL.createObjectURL(file)

  // 設(shè)置預(yù)覽元素的源
  previewEle.src = url
})

使用 FileReader 的 readAsDataURL() 方法

  • 使用 FileReader 對象將文件轉(zhuǎn)換為二進制字符串。然后添加 load 事件偵聽器殿漠,以獲得成功文件上傳的二進制字符串赴精。
  • FileReader.readAsDataURL() 方法用于讀取指定的 BlobFile對象。
// 獲取 FileReader 的實例
const reader = new FileReader()

fileUploader.addEventListener('change', (e) => {
  const files = e.target.files
  const file = files[0]

  // 上傳后獲取文件對象绞幌,以 URL 二進制字符串的形式讀取數(shù)據(jù)
  reader.readAsDataURL(file)

  // 加載后蕾哟,對字符串進行處理
  reader.addEventListener('load', (e) => {
    // 設(shè)置預(yù)覽元素的源
    previewEle.src = reader.result
  })
})

accept 屬性

使用 accept 屬性來限制要上傳的文件類型。

<input type="file" id="file-uploader" accept=".jpg, .png" multiple>

上面示例中莲蜘,瀏覽器將只允許具有 .jpg.png 的文件類型谭确。

驗證文件大小

我們讀取了文件的大小元數(shù)據(jù),可以使用它進行文件大小驗證票渠。您可以允許用戶上傳高達 1MB 的圖像文件逐哈。

// 文件上載更改事件的偵聽器
fileUploader.addEventListener('change', (event) => {
  // 讀取文件大小
  const file = event.target.files[0]
  const size = file.size

  let msg = ''

 // 檢查文件大小是否大于 1MB,提示對應(yīng)消息问顷。
  if (size > 1024 * 1024) {
    msg = `<span style="color: red;">允許的文件大小為 1MB昂秃。您嘗試上載的文件屬于${returnFileSize(size)}</span>`
  } else {
    msg = `<span style="color: green;"> ${returnFileSize(size)} 文件已成功上載。 </span>`
  }

  // 向用戶顯示消息
  feedback.innerHTML = msg
})

顯示文件上傳進度

更好的可用性是讓用戶了解文件上傳進度杜窄。XMLHttpRequest 第二版還定義了一個 progress 事件肠骆,可以用來制作進度條。

先在頁面中放置一個 progress 標(biāo)簽

<label id="progress-label" for="progress"></label>
<progress id="progress" value="0" max="100" value="0">0</progress>

定義 progress 事件的回調(diào)函數(shù)

const reader = new FileReader()

reader.addEventListener('progress', (e) => {
  if (e.loaded && e.total) {
    // 計算完成百分比
    const percent = (e.loaded / e.total) * 100
    // 將值設(shè)置為進度組件
    progress.value = percent
  }
})

上傳目錄

有一個非標(biāo)準(zhǔn)屬性 webkitdirectory塞耕,使我們能夠上傳整個目錄蚀腿。

雖然最初僅針對基于 WebKit 的瀏覽器實施,但 WebkitDirectory 在微軟 Edge 以及 Firefox 50 及以后也可用扫外。然而唯咬,即使它有相對廣泛的支持纱注,它仍然不是標(biāo)準(zhǔn)的,不應(yīng)該使用胆胰,除非你別無選擇狞贱。

<input type="file" id="file-uploader" webkitdirectory />

拖放上傳

主要的 JS 如下:

const dropZone = document.getElementById('drop-zone')
const content = document.getElementById('content')

dropZone.addEventListener('dragover', event => {
  event.stopPropagation()
  event.preventDefault()
  event.dataTransfer.dropEffect = 'copy'
})
dropZone.addEventListener('drop', event => {
  // 獲取文件
  const files = event.dataTransfer.files
  // ..
})

查看效果

用對象處理文件

使用 URL.createObjectURL() 方法從文件創(chuàng)建一個唯一的 URL。使用 URL.revokeObjectURL() 方法釋放它蜀涨。

DOM 和 URL.createObjectURL()URL.revokeObjectURL() 方法允許您創(chuàng)建簡單的 URL 字符串瞎嬉,可用于引用任何可以使用 DOM 文件對象引用的數(shù)據(jù),包括用戶計算機上的本地文件厚柳。

示例:

<div>
  <h1>使用 Object URL</h1>
  <input type="file" id="file-uploader" accept=".jpg, .jpeg, .png" >
  <div id="image-grid"></div>
</div>
const fileUploader = document.getElementById('file-uploader')
const reader = new FileReader()
const imageGrid = document.getElementById('image-grid')

fileUploader.addEventListener('change', (event) => {
  const files = event.target.files
  const file = files[0]
  
  const img = document.createElement('img')
  imageGrid.appendChild(img)
  img.src = URL.createObjectURL(file)
  img.alt = file.name
})
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末氧枣,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子别垮,更是在濱河造成了極大的恐慌便监,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碳想,死亡現(xiàn)場離奇詭異烧董,居然都是意外死亡,警方通過查閱死者的電腦和手機胧奔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門逊移,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人龙填,你說我怎么就攤上這事胳泉。” “怎么了岩遗?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵扇商,是天一觀的道長。 經(jīng)常有香客問我宿礁,道長案铺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任窘拯,我火速辦了婚禮红且,結(jié)果婚禮上坝茎,老公的妹妹穿的比我還像新娘涤姊。我一直安慰自己,他們只是感情好嗤放,可當(dāng)我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布思喊。 她就那樣靜靜地躺著,像睡著了一般次酌。 火紅的嫁衣襯著肌膚如雪恨课。 梳的紋絲不亂的頭發(fā)上舆乔,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天,我揣著相機與錄音剂公,去河邊找鬼希俩。 笑死,一個胖子當(dāng)著我的面吹牛纲辽,可吹牛的內(nèi)容都是我干的颜武。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼拖吼,長吁一口氣:“原來是場噩夢啊……” “哼鳞上!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起吊档,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤篙议,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后怠硼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鬼贱,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年拒名,在試婚紗的時候發(fā)現(xiàn)自己被綠了吩愧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡增显,死狀恐怖雁佳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情同云,我是刑警寧澤糖权,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站炸站,受9級特大地震影響星澳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜旱易,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一禁偎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧阀坏,春花似錦如暖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春枷遂,著一層夾襖步出監(jiān)牢的瞬間樱衷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工酒唉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留矩桂,地道東北人。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓痪伦,卻偏偏與公主長得像耍鬓,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子流妻,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容