使用 JavaScript 上傳和處理不同的文件

在本文中脐供,我們將研究帶有 #upload ID 的 form 元素。

JSON 文件

它包含一個(gè)字段 #file卖陵,帶有一種 type 類型儡嘶。使用 file 類型的字段可以指定 accept 參數(shù),并使用逗號(hào)分隔的接受文件類型列表芜飘。出于我們的目的务豺,我們將把上傳限制為 .json 文件。

<form id="upload">
  <label for="file">文件上傳</label>
  <input type="file" id="file" accept=".json">
  <button>上傳</button>
</form>

我將使用一個(gè)簡(jiǎn)單的 userInfo.json 文件進(jìn)行測(cè)試嗦明。

{
  "name": "O.O",
  "age": "18",
  "hobby": ["Eat", "sleep", "programming"]
}

監(jiān)聽(tīng)上傳

首先笼沥,我們將使用一些 DOM 操作基礎(chǔ)知識(shí)來(lái)檢測(cè)用戶何時(shí)提交文件。

我們將使用 document.querySelector() 方法獲取#upload#file 元素娶牌,并將它們分別保存到 formfile 變量中奔浅。

let form = document.querySelector('#upload')
let file = document.querySelector('#file')

然后,我們將使用 Element.addEventListener() 方法來(lái)監(jiān)聽(tīng) form 元素上的 submit 事件诗良。我們將使用 handleSubmit() 函數(shù)作為回調(diào)函數(shù)汹桦。

form.addEventListener('submit', handleSubmit)

handleSubmit() 函數(shù)內(nèi)部,我們要做的第一件事是 event.preventDefault() 阻止表單重新加載頁(yè)面鉴裹。

/**
 * 處理提交事件
 * @param  {Event} event 事件對(duì)象
 */
function handleSubmit (event) {
  // 阻止表單重新加載頁(yè)面
  event.preventDefault()
}

接下來(lái)营勤,我們將檢查 file 字段是否有要使用該文件處理的實(shí)際文件 file.value 屬性,然后檢查其 length 屬性壹罚。

如果沒(méi)有文件葛作,我們將使用 return 操作符結(jié)束回調(diào)函數(shù)。

function handleSubmit (event) {
  event.preventDefault()

  // 如果沒(méi)有文件猖凛,什么都不要做
  if (!file.value.length) return
}

現(xiàn)在赂蠢,我們已經(jīng)準(zhǔn)備好上傳文件了。

使用 JavaScript 上傳和處理 JSON 文件

FileReader API 是一組異步方法辨泳,允許您處理和讀取文件內(nèi)容虱岂。

我們要做的第一件事是使用 new FileReader() 構(gòu)造函數(shù)創(chuàng)建一個(gè)新的 FileReader 實(shí)例玖院,并將其分配給 reader 變量。

function handleSubmit (event) {
  event.preventDefault()
  if (!file.value.length) return;

  // 創(chuàng)建新的 FileReader() 對(duì)象
  let reader = new FileReader()
}

要真正讀取文件第岖,我們可以使用 FileReader.readAsText() 方法难菌。

我們?cè)?reader 上調(diào)用它,并將文件作為參數(shù)傳遞給 reader蔑滓。我們可以使用文件字段上的 files 屬性訪問(wèn)該文件郊酒。這將返回一個(gè)數(shù)組,因?yàn)?[type="file"] 可以支持多個(gè)文件键袱。

我們將使用括號(hào)表示法獲取第一個(gè)(在本例中是唯一的)文件燎窘。

function handleSubmit (event) {
  event.preventDefault()
  if (!file.value.length) return
  let reader = new FileReader()

  // 讀取文件
  reader.readAsText(file.files[0])
}

這個(gè) API 是異步的,所以我們需要將 onload 事件處理程序附加到 reader 對(duì)象蹄咖。每當(dāng) reader 讀取文件時(shí)褐健,都會(huì)運(yùn)行該命令。

這需要在我們真正讀取文件之前聲明澜汤。

為了讓我們的代碼更有條理蚜迅,我們將使用一個(gè)命名函數(shù):logFile()。我們不希望它立即運(yùn)行俊抵,所以在將其分配給事件時(shí)慢叨,我們不使用括號(hào)(())。

function handleSubmit (event) {
  event.preventDefault()
  if (!file.value.length) return
  let reader = new FileReader()

  // 將回調(diào)事件設(shè)置為在讀取文件時(shí)運(yùn)行
  reader.onload = logFile

  reader.readAsText(file.files[0])
}

logFile() 函數(shù)接收來(lái)自 FileReader 對(duì)象的隱式 event 參數(shù)务蝠,因此我們將其添加為參數(shù)拍谐。

event.target.result 屬性將是上傳的 JSON 文件的字符串化版本。我們可以將它傳遞給JSON.parse()方法以從它獲取 JSON 對(duì)象馏段。

出于我們的目的轩拨,我們將記錄字符串和解析的 JSON。您可能希望在應(yīng)用程序中使用 JSON 文件的屬性院喜,將其保存到 localStorage亡蓉,或者對(duì)其執(zhí)行其他操作。

function logFile (event) {
  let str = event.target.result
  let json = JSON.parse(str)
  console.log('string', str)
  console.log('json', json)
}

現(xiàn)在喷舀,每當(dāng)用戶提交 JSON 文件時(shí)砍濒,我們的代碼都會(huì)讀取它并將其記錄到控制臺(tái)。

圖像文件

更新我們的表單

對(duì)于本文硫麻,我們將更改 [type="file"] 輸入接受的文件類型爸邢。

我們想上傳圖像文件,所以我們將使用 image/* 作為 accept 的值拿愧。如果愿意杠河,您可以將特定的文件擴(kuò)展名指定為逗號(hào)分隔的列表,例如 .png, .jpg

<form id="upload">
  <label for="file">文件上傳</label>
  <input type="file" id="file" accept="image/*">

  <button>上傳</button>
</form>

對(duì)于演示券敌,我還想在 UI 中顯示圖像唾戚,因此我將添加一個(gè) #app 元素,我們可以將圖像渲染到其中待诅。

<div id="app"></div>

使用 JavaScript 上傳圖片

首先叹坦,我們要更新我們的 handleSubmit() 函數(shù)。

我們將不使用 FileReader.readAsText() 方法卑雁,而是使用 FileReader.readAsDataURL() 方法募书,再次傳入文件。這將把文件作為 base64 編碼的數(shù)據(jù) URL 進(jìn)行處理序厉。

function handleSubmit (event) {
  event.preventDefault()
  if (!file.value.length) return
  let reader = new FileReader()
  reader.onload = logFile
  reader.readAsDataURL(file.files[0])
}

接下來(lái),我們將使用 document.querySelector() 方法獲取 #app 元素并將其保存到變量中毕箍。

let app = document.querySelector('#app')

logFile() 事件處理程序函數(shù)中弛房,event.target.result 是圖像文件的數(shù)據(jù) URL 字符串。您可以將其保存到 localStorage而柑,將其發(fā)送到服務(wù)器等等文捶。

因?yàn)槲覀兿朐?UI 中顯示它,所以我們將使用 document.createElement() 方法來(lái)創(chuàng)建一個(gè) img 元素媒咳。然后粹排,我們將從方法返回 event.target.resultFileReader.readAsDataURL() 設(shè)置為 src 屬性。

最后涩澡,我們將使用 Node.append() 方法將其注入 DOM顽耳。

function logFile (event) {
  let str = event.target.result
  let img = document.createElement('img')
  img.src = str
  app.append(img)
  console.log(str)
}

更多資料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市妙同,隨后出現(xiàn)的幾起案子射富,更是在濱河造成了極大的恐慌,老刑警劉巖粥帚,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胰耗,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡芒涡,警方通過(guò)查閱死者的電腦和手機(jī)柴灯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)费尽,“玉大人赠群,你說(shuō)我怎么就攤上這事『涤祝” “怎么了乎串?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我叹誉,道長(zhǎng)鸯两,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任长豁,我火速辦了婚禮钧唐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘匠襟。我一直安慰自己钝侠,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布酸舍。 她就那樣靜靜地躺著帅韧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪啃勉。 梳的紋絲不亂的頭發(fā)上忽舟,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音淮阐,去河邊找鬼叮阅。 笑死,一個(gè)胖子當(dāng)著我的面吹牛泣特,可吹牛的內(nèi)容都是我干的浩姥。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼状您,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼勒叠!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起膏孟,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤缴饭,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后骆莹,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體颗搂,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年幕垦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了丢氢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡先改,死狀恐怖疚察,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仇奶,我是刑警寧澤貌嫡,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響岛抄,放射性物質(zhì)發(fā)生泄漏别惦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一夫椭、第九天 我趴在偏房一處隱蔽的房頂上張望掸掸。 院中可真熱鬧,春花似錦蹭秋、人聲如沸扰付。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)羽莺。三九已至,卻和暖如春洞豁,著一層夾襖步出監(jiān)牢的瞬間盐固,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工族跛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留闰挡,地道東北人锐墙。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓礁哄,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親溪北。 傳聞我的和親對(duì)象是個(gè)殘疾皇子桐绒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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