本文不使用
<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等云存储平台。
-
简历投递与在线应聘:求职者上传简历、作品集或项目演示文件到招聘网站或公司门户。
-
教育平台:学生上传作业、论文或项目报告,教师上传教学资源。
-
博客与论坛:用户上传文章插图、论坛附件或个人签名图片。
-
医疗健康平台:患者上传医疗报告、影像资料,医生上传处方或诊断说明。
-
政府与企业服务:公民或员工上传申请材料、税务文件或企业报告到在线服务平台。