Spring Boot 打包為 JAR 時,src/main/resources/static 會被打入 JAR 內部,無法在運行時動態寫入新檔案。上傳的圖片必須存放在外部文件系統,並配置靜態資源映射對外訪問。
上傳目錄:/data/upload/ (外部磁碟、NFS、S3 掛載點) 訪問 URL:https://host:port/images/xxx.png 映射規則:/images/** → file:/data/upload/
# application.yml
app:
upload:
root-path: /data/upload
url-prefix: /images/**
spring:
servlet:
multipart:
max-file-size: 10MB
max-request-size: 20MB
3. 上傳控制器
4. 前端直傳示例
<input type="file" id="imgInput" accept="image/*"> <button onclick="upload()">上傳</button> <img id="preview" style="max-width:300px;display:none"> <script> function upload() { const file = document.getElementById('imgInput').files[0]; if (!file) return alert('請選擇圖片'); const fd = new FormData(); fd.append('file', file); fetch('/api/upload/image', {method:'POST', body:fd}) .then(r => r.json()) .then(res => { if (res.code === 0) { document.getElementById('preview').src = res.url; document.getElementById('preview').style.display = 'block'; } else alert(res.msg); }); } </script>安全與擴展建議
| 風險/需求 | 對策 |
|---|---|
| 惡意腳本上傳 | 校驗 Content-Type、副檔名、魔數;禁用執行權限 chmod -R -x /data/upload |
| 文件名衝突/遍歷 | UUID 重命名、禁止用戶控制路徑 |
| 大文件/斷點續傳 | 引入 Plupload/WebUploader 分片上傳,後端合併 |
| 多實例共享存儲 | 掛載 NFS、CephFS 或對接 MinIO/S3,配置 ResourceResolver 統一訪問 |
| 圖片處理(壓縮、水印、縮圖) | 上傳後異步調用 Thumbnailator / ImageMagick,存多規格版本 |
| 防盜鏈 | Nginx valid_referers 或簽名 URL 限時訪問 |