在web應(yīng)用程序中使用文件

翻譯自MDN

使用HTML5中添加到DOM的File API,web內(nèi)容現(xiàn)在可以要求用戶選擇本地文件竖幔,然后讀取這些文件的內(nèi)容∈峭担可以通過使用HTML <input>元素或拖放操作來完成此選擇拳氢。

訪問本地文件

html語法:

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

File API可以從 File
對象中讀取FlieList,FlieList中包含了用戶所選取的文件

如果用戶只選取了一個文件,那么我們只需要考慮第一個文件對象

使用DOM讀取選擇的文件:

var selectedFile = document.getElementById('input').files[0];

通過一個change事件訪問選擇的文件

可以通過change事件(不強制)訪問FlieList,

<input type="file" id="input" onchange="handleFiles(this.files)">

當(dāng)用戶選擇一個文件時,handleFiles()函數(shù)將調(diào)用一個FlieList對象蛋铆,該對象包含表示用戶選擇的文件的文件對象馋评。

如果您想讓用戶選擇多個文件,只需使用輸入元素上的multiple屬性:

<input type="file" id="input" multiple onchange="handleFiles(this.files)">

在這種情況下刺啦,傳遞給handleFiles()函數(shù)的文件列表包含用戶所選擇的每個文件的一個文件對象留特。

獲取選中文件的信息

DOM提供的FlieList對象列出由用戶選擇的所有文件,每個文件都指定為一個File
對象。通過檢查文件列表長度屬性的值蜕青,您可以確定用戶選擇了多少個文件:

var numFiles = files.length;

單個文件對象可以通過簡單地訪問列表數(shù)組來檢索:

for (var i = 0, numFiles = files.length; i < numFiles; i++) {
  var file = files[i];
  ..
}

這個循環(huán)遍歷文件列表中的所有文件苟蹈。

File
對象有三個帶有文件信息的屬性

  • name 文件名(只讀),不包含文件路徑信息
  • size 文件大小(只讀),單位是字節(jié)(bytes)
  • type 文件的MIME-type,如果獲取不到文件的MIME-type,則這個屬性就是一個空字符串

示例:顯示文件的大小

下面的示例顯示了可能使用的大小屬性

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>File(s) size</title>
<script>
function updateSize() {
  var nBytes = 0,
      oFiles = document.getElementById("uploadInput").files,
      nFiles = oFiles.length;
  for (var nFileId = 0; nFileId < nFiles; nFileId++) {
    nBytes += oFiles[nFileId].size;
  }
  var sOutput = nBytes + " bytes";
  // optional code for multiples approximation
  for (var aMultiples = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"], nMultiple = 0, nApprox = nBytes / 1024; nApprox > 1; nApprox /= 1024, nMultiple++) {
    sOutput = nApprox.toFixed(3) + " " + aMultiples[nMultiple] + " (" + nBytes + " bytes)";
  }
  // end of optional code
  document.getElementById("fileNum").innerHTML = nFiles;
  document.getElementById("fileSize").innerHTML = sOutput;
}
</script>
</head>

<body onload="updateSize();">
<form name="uploadForm">
<p><input id="uploadInput" type="file" name="myFiles" onchange="updateSize();" multiple> selected files: <span id="fileNum">0</span>; total size: <span id="fileSize">0</span></p>
<p><input type="submit" value="Send file"></p>
</form>
</body>
</html>

使用click()方法使用隱藏的文件輸入元素

從 Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1)開始,您可以隱藏公認的丑陋文件<input>元素,并呈現(xiàn)您自己的接口右核,以打開并顯示用戶選擇的文件慧脱。您可以通過將input元素設(shè)計為display:none并調(diào)用< input >元素的click()方法。

<input type="file" id="fileElem" multiple accept="image/*" style="display:none" onchange="handleFiles(this.files)">
<a href="#" id="fileSelect">Select some files</a>

處理單擊事件的代碼可以如下所示:

var fileSelect = document.getElementById("fileSelect"),
  fileElem = document.getElementById("fileElem");

fileSelect.addEventListener("click", function (e) {
  if (fileElem) {
    fileElem.click();
  }
  e.preventDefault(); // prevent navigation to "#"
}, false);

您可以按您希望的那樣贺喝,樣式化新的按鈕來打開文件選擇器菱鸥。

使用label元素觸發(fā)隱藏的文件輸入元素

<input type="file" id="fileElem" multiple accept="image/*" style="display:none" onchange="handleFiles(this.files)">
<label for="fileElem">Select some files</label>

沒有必要添加JavaScript代碼來調(diào)用文件元素的click()。在這種情況下躏鱼,您可以按照您的希望來樣式化標(biāo)簽元素氮采。

使用拖放來選取文件

您還可以讓用戶將文件拖放到web應(yīng)用程序中。

首先是設(shè)置一個接收的區(qū)域染苛。根據(jù)你的應(yīng)用程序的設(shè)計鹊漠,你的內(nèi)容的不同部分會接受不同的內(nèi)容,但是讓元素接收drop事件是很容易的:

var dropbox;

dropbox = document.getElementById("dropbox");
dropbox.addEventListener("dragenter", dragenter, false); //進入
dropbox.addEventListener("dragover", dragover, false);//移動
dropbox.addEventListener("drop", drop, false);//放下

在本例中,我們將帶ID dropbox的元素轉(zhuǎn)換為我們的drop區(qū)域殖侵。這是通過監(jiān)聽dragenter、dragoverdrop事件來實現(xiàn)的镰烧。

在我們的例子中拢军,我們實際上不需要對dragenterdragover事件做任何事情,所以這些函數(shù)都很簡單怔鳖。他們只是停止傳播事件茉唉,防止發(fā)生默認的行為:

function dragenter(e) {
  e.stopPropagation();
  e.preventDefault();
}

function dragover(e) {
  e.stopPropagation();
  e.preventDefault();
}

真正的魔法發(fā)生在drop()函數(shù)中:

function drop(e) {
  e.stopPropagation();
  e.preventDefault();

  var dt = e.dataTransfer;
  var files = dt.files;

  handleFiles(files);
}

這里,我們從事件中檢索dataTransfer字段结执,將文件列表拉出度陆,然后將其傳遞給handleFiles()。從這一點來看献幔,處理文件的方式與用戶使用輸入元素或拖放的方式是一樣的懂傀。

顯示圖片的縮略圖

假設(shè)您正在開發(fā)下一個偉大的照片共享網(wǎng)站,并希望使用HTML5在用戶實際上傳圖片之前顯示縮略圖預(yù)覽蜡感。您可以像前面討論的那樣建立您的輸入元素或刪除區(qū)域蹬蚁,并將其調(diào)用為以下函數(shù),如handlefile()函數(shù)郑兴。

function handleFiles(files) {
  for (var i = 0; i < files.length; i++) {
    var file = files[i];
    var imageType = /^image\//;
    
    if (!imageType.test(file.type)) {
      continue;
    }
    
    var img = document.createElement("img");
    img.classList.add("obj");
    img.file = file;
    preview.appendChild(img); // Assuming that "preview" is the div output where the content will be displayed.
    
    var reader = new FileReader();
    reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
    reader.readAsDataURL(file);
  }
}

在這里犀斋,我們的循環(huán)處理用戶選擇的文件,查看每個文件的類型屬性情连,看它是否是一個圖像文件(通過在MIME類型字符串模式“image / *”上進行正則表達式匹配)叽粹。對于每個圖像文件,我們創(chuàng)建一個新的img元素。

給每個img對象添加一個file屬性以辨認 File;這將讓我們稍后獲取實際上傳的圖像虫几。使用Node.appendChild()將新縮略圖添加到文檔的預(yù)覽區(qū)域锤灿。

接下來,新建一個FileReader對象來處理異步加載圖像并將其附加到img元素持钉。創(chuàng)建了新的FileReader對象后衡招,設(shè)置onload函數(shù),然后調(diào)用readAsDataURL()以在后臺啟動讀操作每强。當(dāng)加載圖像文件的全部內(nèi)容時始腾,它們將轉(zhuǎn)換為數(shù)據(jù)傳遞給onload回調(diào)的URL。這個示例的實現(xiàn)將img元素的src屬性設(shè)置為加載的圖像空执,結(jié)果顯示在用戶屏幕上的縮略圖中出現(xiàn)的圖像浪箭。

使用 object URLs

Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1) 支持DOM 的 window.URL.createObjectURL()
window.URL.revokeObjectURL()
方法.這些可以創(chuàng)建簡單的URL字符串,可以用來引用任何可以引用DOM File
對象的數(shù)據(jù),包括用戶計算機上的本地文件

當(dāng)您有一個文件對象時辨绊,您希望從HTML中引用URL奶栖,您可以為它創(chuàng)建一個object URL:

var objectURL = window.URL.createObjectURL(fileObj);

object URL是標(biāo)識文件對象的字符串。每次調(diào)用window.URL.createObjectURL()時门坷,都會創(chuàng)建一個唯一的object URL,即使之前已經(jīng)給這個文件創(chuàng)建過一個對象了宣鄙。當(dāng)文檔被卸載時,它們會自動被釋放默蚌,如果你的頁面動態(tài)地使用它們冻晤,你應(yīng)該通過調(diào)用window.URL.revokeObjectURL()顯式地釋放它們

window.URL.revokeObjectURL(objectURL);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市绸吸,隨后出現(xiàn)的幾起案子鼻弧,更是在濱河造成了極大的恐慌,老刑警劉巖锦茁,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件攘轩,死亡現(xiàn)場離奇詭異,居然都是意外死亡码俩,警方通過查閱死者的電腦和手機度帮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來稿存,“玉大人够傍,你說我怎么就攤上這事∧硬” “怎么了冕屯?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長拂苹。 經(jīng)常有香客問我安聘,道長痰洒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任浴韭,我火速辦了婚禮丘喻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘念颈。我一直安慰自己泉粉,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布榴芳。 她就那樣靜靜地躺著嗡靡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪窟感。 梳的紋絲不亂的頭發(fā)上讨彼,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機與錄音柿祈,去河邊找鬼哈误。 笑死,一個胖子當(dāng)著我的面吹牛躏嚎,可吹牛的內(nèi)容都是我干的蜜自。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼卢佣,長吁一口氣:“原來是場噩夢啊……” “哼重荠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起珠漂,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤晚缩,失蹤者是張志新(化名)和其女友劉穎尾膊,沒想到半個月后媳危,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡冈敛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年待笑,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抓谴。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡暮蹂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出癌压,到底是詐尸還是另有隱情仰泻,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布滩届,位于F島的核電站集侯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜棠枉,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一浓体、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧辈讶,春花似錦命浴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至勘伺,卻和暖如春跪腹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背飞醉。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工冲茸, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人缅帘。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓轴术,卻偏偏與公主長得像,于是被迫代替她去往敵國和親钦无。 傳聞我的和親對象是個殘疾皇子逗栽,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,700評論 2 354

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