本文不使用
<input type="file">等前端上傳組件
一、為什么不能使用本地文件路徑上傳?
前端不能直接根據本地文件路徑(例如 C:\Users\Username\Documents\image.jpg
)上傳文件到后端服務器,原因主要在于瀏覽器的安全策略限制。以下是幾個關鍵點解釋這一限制:
-
同源策略(Same-origin policy):瀏覽器實施的安全策略之一,旨在防止不同源的網頁讀取對方的資源。這意味著網頁上的JavaScript無法訪問本地文件系統中的文件,除非這些文件是通過用戶交互(如
<input type="file">
)明確選擇的。 -
沙箱模型(Sandbox model):現代瀏覽器運行JavaScript代碼時,使用沙箱環境來隔離網頁內容,確保網頁腳本不能無授權地訪問用戶計算機上的文件或其他敏感資源。
-
安全限制:直接允許JavaScript訪問和上傳本地文件路徑可能會引發嚴重的安全問題,比如惡意腳本可以未經用戶許可就竊取用戶硬盤上的私人數據。
-
文件API:為了支持文件上傳,HTML5引入了File API,允許Web應用在用戶選擇文件后讀取文件內容,而不是直接操作文件路徑。用戶通過
<input type="file">
選擇文件后,瀏覽器提供文件的臨時虛擬路徑(例如,一個Blob對象或File對象),這些對象可以在JavaScript中操作并上傳到服務器,但不會暴露實際的本地文件系統路徑。
二、實操
1、后端轉base64
我們根據本地的路徑地址轉換為base64編碼傳到前端
public static String convertImageToBase64(String imagePath) {try {// 讀取圖片文件BufferedImage bufferedImage = ImageIO.read(new File(imagePath));// 創建輸出流ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();// 將圖片寫入輸出流,格式為JPEGImageIO.write(bufferedImage, "jpg", byteArrayOutputStream);// 將字節數組轉換為Base64編碼byte[] imageBytes = byteArrayOutputStream.toByteArray();return Base64.getEncoder().encodeToString(imageBytes);} catch (IOException e) {e.printStackTrace();return null;}}
2、前端轉換為Blob對象
從后端傳過來的base64編碼轉換為Blob對象。
// 將base64編碼的數據轉換為Blob對象function base64toBlob(base64Data, contentType = '') {// 設置內容類型contentType = contentType || '';// 將base64編碼的數據轉換為字節字符const byteCharacters = atob(base64Data);// 創建字節數組const byteNumbers = new Array(byteCharacters.length);// 遍歷字節字符,轉換為字節數字for (let i = 0; i < byteCharacters.length; i++) {byteNumbers[i] = byteCharacters.charCodeAt(i);}// 將字節數字轉換為Uint8Arrayconst byteArray = new Uint8Array(byteNumbers);// 創建并返回Blob對象return new Blob([byteArray], {type: contentType});}
3、上傳
再進行對應數據的上傳,切記不能在同一個請求里面多次調用請求方法。所以我們需要進行封裝。
async function uploadFileWithFetch(fileBlob, imagePath) {const formData = new FormData();formData.append('file', fileBlob, imagePath);try {
//文件上傳請求路徑const response = await fetch('/car/distinguish/upload', {method: 'POST',body: formData, // 自動設置Content-Type為multipart/form-data});if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}const result = await response.json();console.log('圖片上傳成功', result.msg + ":" + result.plateNumber);return result;} catch (error) {console.error('圖片上傳失敗', error);}}
在后端我們的 file 里面就可以拿到我們前端上傳的文件了。
@RequestMapping("upload")public Result upload(MultipartFile file)
三、應用場景
這個應用場景主要指的是前端上傳文件到后端的流程,具體包括但不限于以下幾種:
-
社交媒體:用戶上傳個人頭像、分享照片、視頻或文檔到自己的動態或時間線。
-
在線文檔編輯與存儲服務:用戶上傳Word、Excel、PDF等文檔到云端,以便在線預覽、編輯和存儲。
-
電子商務:商家上傳商品圖片、用戶上傳購物評價中的圖片或視頻證據。
-
內容管理系統(CMS):網站管理員或編輯上傳文章配圖、多媒體內容到網站后臺。
-
云存儲服務:用戶上傳個人或工作文件到Dropbox、Google Drive、阿里云OSS等云存儲平臺。
-
簡歷投遞與在線應聘:求職者上傳簡歷、作品集或項目演示文件到招聘網站或公司門戶。
-
教育平臺:學生上傳作業、論文或項目報告,教師上傳教學資源。
-
博客與論壇:用戶上傳文章插圖、論壇附件或個人簽名圖片。
-
醫療健康平臺:患者上傳醫療報告、影像資料,醫生上傳處方或診斷說明。
-
政府與企業服務:公民或員工上傳申請材料、稅務文件或企業報告到在線服務平臺。