文件上传Demo
文件上传-本地上传
概述
使用场景
文件上传是程序开发中都会用到的一个需求,一般用来共享资源。比如:
- 添加用户头像,文章封面…
- 富文本编辑(插件文件上传)
原理
用户选择文件发送request
请求,程序将文件通过Java-IO流
复制到服务器即为文件上传
用SpringBoot实现文件上传
1. 实现步骤
01. 搭建SpringBoot工程
- 新建项目
- 配置端口
server:port: 8888spring:freemarker:suffix: .htmlcache: false
02. 准备文件上传的前端页面
- 创建
resources/templates/upload.html
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>文件上传</title></head><body><h1 style="text-align: center">文件上传</h1><form action="/upload/file" enctype="multipart/form-data" method="post"><input name="dir" value="bbs"><input name="file" type="file"><input type="submit" value="文件上传"></form></body></html>
03. 实现文件上传的后端逻辑
- 定义文件上传service:
UploadService
此处需要注意:
mkdirs()
可建立多级文件夹mkdir()
只建立一级文件夹
package com.yue.service;import org.springframework.stereotype.Service;import org.springframework.web.multipart.MultipartFile;import java.io.File;import java.io.IOException;/** * @Author: 夜雨 * Create Date Time: 2022-02-26-21:54 * Update Date Time: * @Version 1.0 * @Description: * @see */@Servicepublic class UploadService {/** * @Discription: MultipartFile对象是一个SpringMVC提供的文件上传接收类 * 其底层会自动去与HttpServletRequest request中的request.getInputStream()融合,从而实现文件上传 * 所以:文件上传底层原理就是request.getInputStream() * @param multipartFile * @param dir * @return java.lang.String * @Author: 夜雨 * @Date: 2022/3/1 20:55 */public String uploadImg(MultipartFile multipartFile,String dir){File targetFile = new File("G://tmp/"+dir);try {if (!targetFile.exists())targetFile.mkdir();multipartFile.transferTo(targetFile);return "上传成功";} catch (IOException e) {e.printStackTrace();return "上传失败!";}}}
- 定义文件上传controller:UploadController
package com.yue.controller;import com.yue.service.UploadService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletRequest;/** * @Author: 夜雨 * Create Date Time: 2022-02-26-21:53 * Update Date Time: * @Version 1.0 * @Description: * @see */@Controllerpublic class UploadController {@Autowiredprivate UploadService uploadService;/** * @Discription: 文件上传 * @param multipartFile * @param request * @return java.lang.String * @Author: 夜雨 * @Date: 2022/2/28 21:27 */@PostMapping("/upload/file")@ResponseBodypublic String upload(@RequestParam("file") MultipartFile multipartFile, HttpServletRequest request){if (multipartFile.isEmpty()){return "文件有误!";}String dir = request.getParameter("dir");return uploadService.uploadImg(multipartFile,dir);}}
- 测试上传,在后台看到如下:
SpringMVC提供了MultipartFile包装对象,原理如下:
通过MultipartFile 我们很清楚的看到,文件已经被服务器接收。
但是会产生一个临时目录,这个目录是可以去配置
文件上传不会直接上传真正的目录,它一定要经过一个临时目录的中转以后,才会上传到真正的目录。作用:
- 防止上传出现网络断开,或者用户上传直接刷新或者取消。因为如果用户的网络断开或者取消,就造成大量的垃圾文件
- 保证真实目录上传的文件一定是有效的。
- 文件上传的大小:也可以进行配置的
- 文件上传的类型:也是进行配置的
server:port: 8888spring:freemarker:suffix: .htmlcache: falseservlet:multipart:enabled: true#当文件大小达到多少时进行磁盘写入file-size-threshold: 1KB#单个文件的最大值(默认1MB)max-file-size: 50MB#一次性上传文件的最大值max-request-size: 800MB#指定临时目录location: D://data//temptest
注意配置临时目录的时候需要些两个“/”,因为需要转义
04. 配置静态资源存储服务(指定文件存储目录)
增加日期目录,确定文件存放最终目录
package com.yue.service;import org.springframework.stereotype.Service;import org.springframework.web.multipart.MultipartFile;import java.io.File;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.*;/** * @Author: 夜雨 * Create Date Time: 2022-02-26-21:54 * Update Date Time: * @Version 1.0 * @Description: * @see */@Servicepublic class UploadService<contentType> {private ArrayList<String> contentTypeList;/** * @Discription: MultipartFile对象是一个SpringMVC提供的文件上传接收类 * 其底层会自动去与HttpServletRequest request中的request.getInputStream()融合,从而实现文件上传 * 所以:文件上传底层原理就是request.getInputStream() * @param multipartFile * @param dir * @return java.lang.String * @Author: 夜雨 * @Date: 2022/3/1 20:55 */public String uploadImg(MultipartFile multipartFile,String dir) {//1.指定文件上传目录try {//1.获取文件名String realFilename = multipartFile.getOriginalFilename();//2.截取文件后缀名String imgSuffix = realFilename.substring(realFilename.lastIndexOf("."));//3.生成唯一文件名(不能使用中文命名,在网页访问过程中统一英文命名,中文名可能会出现乱码,需要进一步处理)String newFilename = UUID.randomUUID().toString() + imgSuffix;//4.生成日期目录SimpleDateFormat dateFormat = new SimpleDateFormat("yyy/MM/dd");String dataPath = dateFormat.format(new Date());//5.指定最终目录File targetPath = new File("D://tmp/" + dir, dataPath);if (!targetPath.exists()) targetPath.mkdirs();//不存在目录则创建//6.指定文件上传后服务器的完整文件名File targetFileName = new File(targetPath, newFilename);//7.文件上传multipartFile.transferTo(targetFileName);return "上传成功";} catch (IOException e) {e.printStackTrace();return "上传失败!";}}}
限制上传文件的类型(类型隔离)
- 前端实现:
“accept”属性:接收类型
<form action="/upload/file" enctype="multipart/form-data" method="post"><input name="dir" value="bbs"><input name="file" type="file" accept="image/png"><input type="submit" value="文件上传"></form>
作用:上传文件时自动过滤类型,但是仍可以在前端手动选择所有文件,所以文件类型限制一般在后端实现。
- 后端实现