前端文件上傳與下載攻略
本文目標:幫你快速掌握文件上傳 & 下載的核心實現方式,并在常見出錯場景下保持“優雅不崩潰”。
一、文件上傳
1. 基礎結構
<input type="file" id="fileInput" />
<button id="uploadBtn">上傳</button>
2. 核心腳本
document.getElementById('uploadBtn').addEventListener('click', uploadFile);async function uploadFile () {const file = fileInput.files?.[0]; // ① 是否選擇文件if (!file) return alert('請先選擇文件!');const formData = new FormData();formData.append('file', file);try {const res = await fetch('/upload', { // ② 發請求method: 'POST',body: formData,});if (!res.ok) throw new Error(`HTTP ${res.status}`);const data = await res.json(); // ③ 處理業務結果alert(`上傳成功:${data.filename}`);} catch (err) {console.error(err);alert(`上傳失敗:${err.message}`); // ④ 兜底提示}
}
? 重點錯誤防護
- 未選文件:
if (!file) …
。 - 網絡/HTTP 錯誤:
!res.ok
判定 & 拋錯。 - 接口業務錯誤:后端自定義 code → 前端根據
data.code
決策 UI。 - 超大文件 / 類型不符:后端校驗 → 返回 413/415,前端同樣走
!res.ok
分支。
二、文件下載
場景 1:文件已存在靜態 URL
<a href="/static/report.pdf" download="報告.pdf">下載報告</a>
場景 2:前端生成 / 動態獲取文件
async function downloadDynamic () {try {// ① 拿到二進制(示例:后臺生成 excel)const res = await fetch('/export/excel');if (!res.ok) throw new Error(`HTTP ${res.status}`);const blob = await res.blob(); // ② 轉 blobconst url = URL.createObjectURL(blob); // ③ 臨時鏈接// ④ 觸發下載const a = document.createElement('a');a.href = url;a.download = 'data.xlsx';a.click();URL.revokeObjectURL(url); // ⑤ 釋放內存} catch (err) {alert(`下載失敗:${err.message}`);}
}
?? 常見下載錯誤處理
錯誤場景 | 瀏覽器表現 | 前端防范思路 |
---|---|---|
鏈接 404 / 403 | 瀏覽器提示/空白頁 | !res.ok 捕獲 + 友好提示 |
權限不足 | 返回 401/403 | 跳登錄頁或提示“無權限下載” |
內容空 / 后端異常 | 文件 0?B | blob.size === 0 時提示并中斷 |
三、實戰加分 Tips
- 進度條
const xhr = new XMLHttpRequest(); xhr.upload.onprogress = e => {if (e.lengthComputable) {const percent = (e.loaded / e.total) * 100;console.log(`已上傳 ${percent.toFixed(1)}%`);} };
- 多文件并發上傳:
Array.from(fileInput.files).map(f => formData.append('files', f))
。 - 拖拽上傳:監聽
dragover / drop
,獲取event.dataTransfer.files
。 - 斷點續傳:結合
Content-Range
+ 后端分片合并。 - 安全防護:
- 前端白名單校驗 MIME / 后綴。
- token/簽名防盜鏈。
- HTTPS 保障傳輸安全。
四、結語
實現文件上傳與下載并不難,難的是在各種異常面前穩如老狗。
- 上傳要三查:文件、網絡、后端業務。
- 下載要三穩:合法鏈接、正確權限、完整內容。