在html5中,DOM給檔案中新增了一個files集合,在選取檔案中,files中包含一個File物件,每個物件都有下列屬性:
- name: 本地檔案的檔名
- size:檔案的大小
- type: 字串,檔案的MIME型別
- lastModifiedDate: 字串,檔案上一次被修改的時間
同時,使用FileReader物件,web應用程式可以非同步的讀取儲存在使用者計算機上的檔案(或者原始資料緩衝)內容,可以使用File物件或者Blob物件來指定所要處理的檔案或資料。FileReader 提供瞭如下 幾個方法。
- readAsText(file,encoding):以純文字形式讀取檔案,將讀取到的文字儲存在 result 屬 性中。第二個引數用於指定編碼型別,是可選的。
- readAsDataURL(file):讀取檔案並將檔案以資料 URI的形式儲存在 result 屬性中。
- readAsBinaryString(file):讀取檔案並將一個字串儲存在 result 屬性中,字串中的 每個字元表示一位元組。
- readAsArrayBuffer(file):讀取檔案並將一個包含檔案內容的 ArrayBuffer 儲存在 result 屬性中。 這些讀取檔案的方法為靈活地處理檔案資料提供了極大便利。例如,可以讀取影象檔案並將其儲存 為資料 URI,以便將其顯示給使用者,或者為了解析方便,可以將檔案讀取為文字形式。
先來個例子
需求:若讀取檔案為圖片,則以img展示出來,其他情況則以text的形式輸出。
- 若要讀取檔案,首先需要一個input元素
<input type="file" id="files-list">
複製程式碼
- 接下來,若讀取的檔案為圖片,使用readAsDataURL將其轉化為圖片,否則轉化為text。 相應的轉化結果會儲存在result中。
reader = new FileReader();
if (/image/.test(files[0].type)) {
// 選擇檔案型別為圖片
reader.readAsDataURL(files[0]);
type = "image";
} else {
// 其他檔案型別,並指定編碼型別
reader.readAsText(files[0], 'gb2312');
type = "text";
}
複製程式碼
- 讀取完成後,將圖片利用img標籤展示出來;若為text則掛載在頁面上
reader.onload = function () {
var html = "";
switch (type) {
case "image":
html = "<img src=\"" + reader.result + "\">";
break;
case "text":
html = reader.result;
console.log(html);
break;
}
output.innerHTML = html;
};
複製程式碼
讀取圖片
讀取csv檔案
在利用readAsText進行讀取的時候,要指定一下編碼形式。如readAsText(files[0], 'gb2312');
複製程式碼
csv的匯入
csv檔案的特點: 每一行用換行符進行分隔,每一行的資料中每一項利用逗號分隔。
複製程式碼
上面已經可以將csv作為text進行輸出了。下來繼續拿取資料。
利用上面所說的csv的特點就可以利用js進行迴圈遍歷拿到每一項的資料。
其中,我將CVS中的資料轉化後,並拼在了table元素中:
// 將讀取的資料轉化為table
function textToCsv(data) {
var allRows = data.split(/\n/);
var table = '<table>';
for (var singleRow = 0; singleRow < allRows.length - 1; singleRow++) {
if (singleRow === 0) {
table += '<thead>';
table += '<tr>';
} else {
table += '<tr>';
}
var rowCells = allRows[singleRow].split(',');
for (var rowCell = 0; rowCell < rowCells.length; rowCell++) {
if (singleRow === 0) {
// 表格的標題
table += '<th>';
table += rowCells[rowCell];
table += '</th>';
} else {
// 表格內容
table += '<td>';
table += rowCells[rowCell];
table += '</td>';
}
}
if (singleRow === 0) {
table += '</tr>';
table += '</thead>';
table += '<tbody>';
} else {
table += '</tr>';
}
}
table += '</tbody>';
table += '</table>';
console.log(table);
document.getElementById('table').innerHTML = table;
}
複製程式碼
效果圖如下:
既然都讀取出來,下載?
關於下載的操作,可以藉助於a標籤。先介紹下相關的屬性:
- download: 用於指定下載的檔名
- href:為所要下載的檔案的連結(需為本地連結)
上一個列子的下載就是用的上面的做法:
<a href="./file/會員.csv" download="demo.csv">下載測試檔案</a>
複製程式碼
先準備資料 csv檔案的頭部資料:
var head = [
['姓名(最多10個字)', '手機號(必填)', '等級', '生日(比如:1989/08/08 或 1989-08-08)', '積分(限整數)']
];
複製程式碼
csv檔案的主體資料:
var people = [{
"name": "吳三桂",
"phone": "18709237410",
"level": "黃金",
"birthday": "1989/8/5",
"points": "100"
}, {
"name": "史泰龍",
"phone": "18709237401",
"level": "青銅2",
"birthday": "1993/9/6",
"points": "300"
}, {
"name": "阿超",
"phone": "18883920287",
"level": "白金",
"birthday": "1993/9/3",
"points": "500"
}];
複製程式碼
下來就是資料的格式轉換:
//. 將資料push到大陣列中
var p = people;
for (var i = 0; i < p.length; i++) {
head.push([p[i].name, p[i].phone, p[i].level, p[i].birthday, p[i].points]);
}
// 按照csv檔案內容格式,把每個陣列用 , 連線,形成一行,並存入新陣列
var csvRows = [];
for (var j = 0; j < head.length; j++) {
csvRows.push(head[j].join(','))
}
//s4. 把新陣列用 \n 回車連線
var csvString = csvRows.join('\n');
複製程式碼
最後實現下載:
//利用a標籤實現下載
function saveAs(obj, fileName) {
var tmpa = document.createElement("a");
tmpa.download = fileName || "下載.csv";
tmpa.href ='data:attachment/csv,' + encodeURI(obj); //繫結a標籤
tmpa.click(); //模擬點選實現下載
setTimeout(function () { //延時釋放
URL.revokeObjectURL(obj); //用URL.revokeObjectURL()來釋放這個object URL
}, 100);
}
複製程式碼
演示連結
效果圖
下面將使用js-xlsx對csv檔案進行操作:
excel檔案讀取
xlsx相關api:
- XLSX.utils.sheet_to_json方法解析表格物件返回相應的JSON資料
- XLSX.read()以二進位制流方式讀取excel資料
在JavaScript中,有2個函式分別用來處理解碼和編碼base64 字串:
- atob() 函式能夠解碼通過base-64編碼的字串資料。
- btoa() 函式能夠從二進位制資料“字串”建立一個base-64編碼的ASCII字串。
步驟:
- readAsArrayBuffer可以將讀取的資料轉化為二進位制資料;
- 通過btoa()將資料轉化為base64格式;
- 然後結合XLSX.utils.sheet_to_json轉化為json
var wb;//讀取完成的資料
//匯入
function importf(obj) {
if (!obj.files) {
return;
}
var f = obj.files[0];
var reader = new FileReader();
reader.readAsArrayBuffer(f);
reader.onload = function (e) {
var data = e.target.result;
var wb =XLSX.read(btoa(fixedData(data)), { type: 'base64' });//將資料轉化為二進位制
//wb.SheetNames[0]是獲取Sheets中第一個Sheet的名字
//wb.Sheets[Sheet名]獲取第一個Sheet的資料
document.getElementById("excel").innerHTML = JSON.stringify(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]));
};
}
複製程式碼
//檔案流轉BinaryString
function fixedData(data) {
let o = ''
let l = 0
const w = 10240
for (; l < data.byteLength / w; ++l) o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w,
l * w + w)))
o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w)))
return o
}
複製程式碼
效果圖預覽:
檢視演示附上一個vue-element-admin關於Excel檔案讀取的原始碼: 檢視連結
Excel檔案匯出
這裡依然會用到js-xlsx, 檔案下載採用FileSaver.js
<button onclick="downloadExl(people)">匯出</button>
複製程式碼
- 資料準備
var people = [{
"name": "吳三桂",
"phone": "18709237410",
"level": "黃金",
"birthday": "1989/8/5",
"points": "100"
}, {
"name": "史泰龍",
"phone": "18709237401",
"level": "青銅2",
"birthday": "1993/9/6",
"points": "300"
}, {
"name": "阿超",
"phone": "18883920287",
"level": "白金",
"birthday": "1993/9/3",
"points": "500"
}];
複製程式碼
下來定義一個wb儲存匯出資料
var wb = {
SheetNames: ["Sheet1"], //標題名
Sheets: { } //儲存表內的資料
}
複製程式碼
- XLSX.utils.json_to_sheet(people):可以將json物件轉化為工作表;將轉化的結果賦值非 wb.Sheets['Sheet1']
!ref: 表示表格輸出的範圍
A1-Zx: 這些就對應的是Excel中單元格的位置;
其中:Sheet1相關引數介紹:
鍵名 | 值 |
---|---|
v | 原始值 |
t | b布林值,e錯誤,n數字,d日期,s文字 |
更多屬性請參照: 官方文件
- 指定匯出格式,這裡採用xlsx格式
const wopts = { bookType: 'xlsx', bookSST: false,type: 'binary' };
//這裡的資料是用來定義匯出的格式型別
// const wopts = { bookType: 'csv', bookSST: false, type: 'binary' };//ods格式
// const wopts = { bookType: 'ods', bookSST: false, type: 'binary' };//ods格式
// const wopts = { bookType: 'xlsb', bookSST: false, type: 'binary' };//xlsb格式
// const wopts = { bookType: 'fods', bookSST: false, type: 'binary' };//fods格式
// const wopts = { bookType: 'biff2', bookSST: false, type: 'binary' };//xls格式
複製程式碼
- 設定表頭 將工作表的A1-Z1等替換稱為中文
// 將指定的自然數轉換為26進製表示。對映關係:[0-25] -> [A-Z]。
function getCharCol(n) {
var temCol = '',
s = '',
m = 0
while (n >= 0) {
m = n % 26 + 1
s = String.fromCharCode(m + 64) + s
n = (n - m) / 26
}
return s
};
["ID","手機號","等級" ,"生日","積分"].forEach((v,i)=>{data[getCharCol(i)+1] = { t: "s", v: v ,w:v};})
複製程式碼
- 下載儲存,
利用XLSX.write(wb, wopts);
wb: 二進位制資料流
wopts: 指定的匯出格式等資訊
下載儲存這次不採用a標籤的方式。採用FileSaver.js
saveAs(new Blob([s2ab(XLSX.write(wb, wopts))], {type: "application/octet-stream"}), "js-xlsx檔案下載例項" + '.' + wopts.bookType);
複製程式碼
新人首次發帖,,大家勿噴!!!
參考文章: