這是《大胖小課》欄目的專題一《說說檔案上傳那些事兒》的第3節-《不用 js 實作檔案無重新整理上傳》
專題已經更新章節:
《大胖 • 小課》- 我是這樣了解檔案上傳的
《大胖 • 小課》- 寫一個 node 的檔案上傳接口
上一節,我們實作了一個簡單的檔案上傳接口,服務端的檔案儲存我們使用
koa-body
來完成。
從這節開始我們開始進行梳理前端各種檔案上傳的場景。
既然要說不用
js
實作檔案無重新整理上傳,那就要先說說最原始的檔案上傳,也就是在
ie
時代是怎麼處理的。
最原始的檔案上傳
使用 form 表單上傳檔案在
ie
時代,如果實作一個無重新整理的檔案上傳那可是費老勁了,大部分都是用 iframe 來實作局部重新整理或者使用 flash 插件來搞定,在那個時代
ie
就是最好用的浏覽器(别無選擇)。
DEMO

這種方式上傳檔案,不需要 js ,而且沒有相容問題,所有浏覽器都支援,就是體驗很差,導緻頁面重新整理,頁面其他資料丢失。
HTML
<form method="post" action="http://localhost:8100" enctype="multipart/form-data">
選擇檔案:
<input type="file" name="f1"/> input 必須設定 name 屬性,否則資料無法發送<br/>
<br/>
标題:<input type="text" name="title"/><br/><br/><br/>
<button type="submit" id="btn-0">上 傳</button>
</form>
多檔案上傳
在
ie
時代的多檔案上傳是需要建立多個
input file
标簽,現在
html5
隻需要一個标簽加個屬性就搞定了,
file
标簽開啟
multiple
。
DEMO
HTML
//設定 multiple屬性
<input type="file" name="f1" multiple/>
NODE
檔案上傳接口也需要進行簡單的調整,由單檔案對象的擷取變為多檔案數組,然後進行周遊處理。
//中間件處理檔案重命名
app.use((ctx) => {
var files = ctx.request.files.f1;// 多檔案, 得到上傳檔案的數組
var result=[];
//周遊處理
files && files.forEach(item=>{
var path = item.path;
var fname = item.name;//原檔案名稱
var nextPath = path + fname;
if (item.size > 0 && path) {
//得到擴充名
var extArr = fname.split('.');
var ext = extArr[extArr.length - 1];
var nextPath = path + '.' + ext;
//重命名檔案
fs.renameSync(path, nextPath);
//檔案可通路路徑放入數組
result.push(uploadHost+ nextPath.slice(nextPath.lastIndexOf('/') + 1));
}
});
//輸出 json 結果
ctx.body = `{
"fileUrl":${JSON.stringify(result)}
}`;
})
CODE
https://github.com/Bigerfe/fe-learn-code/tree/master/src/upfiles-demo/demo2
局部重新整理(不用 js 的無重新整理上傳) - iframe
這裡說的是在
ie
時代的上傳檔案局部重新整理,借助 iframe 實作。
DEMO
- 局部重新整理
頁面内放一個隐藏的
iframe
,或者使用
js
動态建立,指定
form
表單的
target
屬性值為
iframe
标簽 的
name
屬性值,這樣
form
表單的
shubmit
行為的跳轉就會在
iframe
内完成,整體頁面不會重新整理。
- 拿到接口資料
然後為
iframe
添加
load
事件,得到
iframe
的頁面内容,将結果轉換為
JSON
對象,這樣就拿到了接口的資料
HTML
<iframe id="temp-iframe" name="temp-iframe" src="" style="display:none;"></iframe>
<form method="post" target="temp-iframe" action="http://localhost:8100" enctype="multipart/form-data">
選擇檔案(可多選):
<input type="file" name="f1" id="f1" multiple/><br/> input 必須設定 name 屬性,否則資料無法發送<br/>
<br/>
标題:<input type="text" name="title"/><br/><br/><br/>
<button type="submit" id="btn-0">上 傳</button>
</form>
<script>
var iframe = document.getElementById('temp-iframe');
iframe.addEventListener('load',function () {
var result = iframe.contentWindow.document.body.innerText;
//接口資料轉換為 JSON 對象
var obj = JSON.parse(result);
if(obj && obj.fileUrl.length){
alert('上傳成功');
}
console.log(obj);
});
</script>
NODE
服務端代碼不需要改動,略.
CODE
https://github.com/Bigerfe/fe-learn-code/tree/master/src/upfiles-demo/demo3
小結
本節主要是介紹了下在 ie 時代通常是怎樣實作檔案上傳和無重新整理上傳的,雖然現在的大前端時代已經支援體驗更好的方式實作,但是本質的原理都不會變,隻是工具(浏覽器)更新了。
作者 zz_jesse, 專注前端領域,深更原理和實作,目前在公司主要負責技術架構和團隊管理。
個人開源項目 :react ssr 開發骨架 Zz.js, https://github.com/Bigerfe/koa-react-ssr
個人公衆号:@《前端張大胖》 歡迎關注,深度好文以及各種福利在等你。