[筆記] JavaScript 按鈕自動下載類型與程式碼

這回在實務上遇上:讓使用者在點「下載」按鈕後,就幫使用者自動下載到本機端。這邊筆記下可能會用到的常用類型方法,以及要注意的事項。

javascript es6 logo


說明

PDF, Microsoft Office 系列檔案

若是一般的文件系列檔案,這在 HTML5 的預設行為中是可以直接被下載下來的,所以你僅需要在使用者點選按鈕後,幫使用者建立一個 <a> 標籤、加上 download 和 href 的內容,再幫使用者點選即可

圖片和 txt 文字檔

由於瀏覽器預設是會「另開視窗」打開這兩個檔案,並不會自動幫你下載到本機端。因此,你需要先行將圖片和文字先取到本機端後,產生一個 local 端地暫存。接著用幫使用者點下這個暫存檔的所在連結。

注意事項

需要注意 CORS 的問題。若後端伺服器並沒有回傳對應的 Response Header,那就有機會被瀏覽器給拒絕而無法下載。


程式碼

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Auto Download File and Save Demo</title>
</head>
<body>
<div class="buttons" style="display:flex; flex-wrap:nowrap">
<button id="download-btn-image" style="margin:0 8px;">
Download Image
</button>
<button id="download-btn-pdf" style="margin:0 8px;">
Download PDF
</button>
<button id="download-btn-xlsx" style="margin:0 8px;">
Download Spreadsheet (.xlsx)
</button>
<button id="download-btn-doc" style="margin:0 8px;">
Download Word File
</button>
<button id="download-btn-txt" style="margin:0 8px;">
Download Txt
</button>
<button id="download-btn-ppt" style="margin:0 8px;">
Download PowerPoint
</button>
</div>
<script src="./auto-download-file-and-save-demo.js"></script>
</body>
</html>
const demoTypeList = [
{ type: 'image', url: 'https://upload.wikimedia.org/wikipedia/commons/5/57/Binance_Logo.png' },
{ type: 'pdf', url: 'https://abseil.io/resources/swe_at_google.2.pdf' },
{ type: 'xlsx', url: 'https://www.google.com/help/hc/downloads/sa360/Location-Language-Codes-GoogleAds.xlsx' },
{ type: 'doc', url: 'https://www-03.ibm.com/software/sla/sladb.nsf/8bd55c6b9fa8039c86256c6800578854/6fb5af3e1e25830e8525843200220908/$FILE/i126-8560-01_07-2019_zh_TW.docx' },
{ type: 'txt', url: 'https://www.easy168.tw/urllist.txt' },
{ type: 'ppt', url: 'https://sysh.tc.edu.tw/var/file/64/1064/img/545856627.ppt' }
]
demoTypeList.forEach(item => {
initBtnDownload(item)
})
function initBtnDownload(item){
switch (item.type){
case 'txt':
document.querySelector(`#download-btn-${item.type}`)
.addEventListener('click', async function (event) {
try {
const txtRaw = await (await fetch(item.url)).text()
const txtBlob = new Blob([txtRaw], { type: "text/plain;charset=utf-8" })
const txtURL = URL.createObjectURL(txtBlob)
const aLinkDOM = document.createElement('a')
aLinkDOM.href = txtURL
aLinkDOM.download = 'demo.txt'
document.body.appendChild(aLinkDOM)
aLinkDOM.click()
document.body.appendChild(aLinkDOM)
} catch (err) {
console.log(err)
}
})
break
case 'image':
document.querySelector(`#download-btn-${item.type}`)
.addEventListener('click', async function (event) {
try {
const image = await fetch(item.url)
const imageBlob = await image.blob()
const imageURL = URL.createObjectURL(imageBlob)
const aLinkDOM = document.createElement('a')
aLinkDOM.href = imageURL
aLinkDOM.download = ''
document.body.appendChild(aLinkDOM);
aLinkDOM.click()
document.body.removeChild(aLinkDOM);
URL.revokeObjectURL(imageURL)
} catch (err) {
console.log(err)
}
})
break
default:
document.querySelector(`#download-btn-${item.type}`).addEventListener('click', function (event) {
const aLinkDom = document.createElement('a')
aLinkDom.href = item.url
aLinkDom.download = ''
document.body.appendChild(aLinkDom);
aLinkDom.click()
document.body.removeChild(aLinkDom);
})
break
}
}

按讚加入粉絲團

延伸閱讀