14、SpringBoot实现⽂件上传与下载(数据库版)
需求
不过这种⽅法局限性很⼤:
图⽚存储的位置写死,不可以灵活配置。
没有专门实现“下载”,虽然可以直接预览例如浏览器输⼊图⽚地址,localhost:8080/image/1.jpg,可以直接预览图⽚,但是如果想下载,必须右击选择下载到本地。
直接把⽂件放在项⽬⼯程⾥⾯,项⽬臃肿,服务器压⼒很⼤。
⽂件名写死,⽆法保留原⽂件的⽂件名。
现在新的需求是:
⽂件保存的路径可以配置。
可以通过⽂件名等标识符,下载指定⽂件。
保留⽂件原有的名称,在下载的时候可以指定新的⽂件名,也可以⽤原先的⽂件名。
可以指定只能上传特定格式的⽂件,例如word⽂档、压缩包、excel表格等。
思路
注意:
数据库只存放⽂件的描述信息(例如⽂件名、所在路径),不存⽂件本⾝。
上传流程:
(1)⽤户点击上传⽂件 ——> (2)传到后台服务器——>(3)初步校验,上传的⽂件不能为空——>(4)唯⼀性校验,如果你的项⽬只能存在⼀个⽂件,必须把已有的⽂件删去(可选)——> (5) 检查是否有同名⽂件,同名⽂件是否覆盖(可选)
——> (6) 开始上传⽂件 ——> (7) 检查⽂件类型是否满⾜需求——> (8) ⽤⼀个变量保留原有的名字,将⽂件写⼊服务器本地 ——> (9) 如果写⼊成功,将路径、新的⽂件名、旧的⽂件名、⽂件的功能 等等写⼊数据库。
下载流程:
从数据库取出指定⽂件的描述信息,描述信息⾥⾯有⽂件所在⽬录,⽤java的api获取⽂件对象,转化成字节写⼊response,返回给前端。
完整实现
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
SpringBoot版本
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
⽬录结构
⽂件上传⼯具类
⽂件上传⼯具类有三个,功能不⼀致。
FileUploadUtils
******可以在这⾥修改⽂件默认存放位置
上传⽂件,⽀持默认路径存储、也⽀持指定⽬录存储。
在SpringBoot还需要在配置⽂件中配置上传⽂件的⼤⼩上限,默认是2MB。
public class FileUploadUtils {
/**
* 默认⼤⼩ 50M
*/
public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;
/**
* 默认的⽂件名最⼤长度 100
*/
public static final int FILE_NAME_MAX = 100;
/
**
* 默认上传的地址
*/
private static String DEFAULT_BASE_FILE = "D:\\personalCode\\activemq-learn\\file-upload-learn\\src\\main\\resources\\upload"; /**
* 按照默认的配置上床⽂件
*
* @param file ⽂件
* @return⽂件名
* @throws IOException
*/
public static final String upload(MultipartFile file) throws IOException {
try {
return upload(FileUploadUtils.DEFAULT_BASE_FILE, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
} catch (Exception e) {
throw new Message(), e);
}
}
/**
* 根据⽂件路径上传
*
* @param baseDir 相对应⽤的基⽬录
* @param file    上传的⽂件
* @return⽂件名称
* @throws IOException
*/
public static final String upload(String baseDir, MultipartFile file) throws IOException {
try {
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
} catch (Exception e) {
throw new Message(), e);
}
}
/**
* ⽂件上传
* @param baseDir          相对应⽤的基⽬录
* @param file            上传的⽂件
* @param allowedExtension 上传⽂件类型
* @return返回上传成功的⽂件名
* @throws FileSizeLimitExceededException 如果超出最⼤⼤⼩
* @throws IOException                    ⽐如读写⽂件出错时
*/
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension) throws Exception {
//合法性校验
assertAllowed(file, allowedExtension);
String fileName = encodingFileName(file);
File desc = getAbsoluteFile(baseDir, fileName);
AbsolutePath();
}
private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException {        File desc = new File(uploadDir + File.separator + fileName);
if (!ParentFile().exists()) {
}
if (!ists()) {
}
return desc;
}
/**
* 对⽂件名特殊处理⼀下
*
* @param file ⽂件
* @return
*/
private static String encodingFileName(MultipartFile file) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String datePath = simpleDateFormat.format(new Date());
return datePath + "-" + UUID.randomUUID().toString() + "." + getExtension(file);
}
/**
* ⽂件合法性校验
*
* @param file 上传的⽂件
* @return
*/
public static final void assertAllowed(MultipartFile file, String[] allowedExtension) throws Exception {
if (OriginalFilename() != null) {
int fileNamelength = OriginalFilename().length();
if (fileNamelength > FILE_NAME_MAX) {
throw new Exception("⽂件名过长");
}
}
long size = Size();
if (size > DEFAULT_MAX_SIZE) {
throw new Exception("⽂件过⼤");
}
String extension = getExtension(file);
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) {
throw new Exception("请上传指定类型的⽂件!");
}
}
/**
* 判断MIME类型是否是允许的MIME类型mysql存储文档
*
* @param extension
* @param allowedExtension
* @return
*/
public static final boolean isAllowedExtension(String extension, String[] allowedExtension) { for (String str : allowedExtension) {
if (str.equalsIgnoreCase(extension)) {
return true;
}
}
return false;
}
/**
* 获取⽂件名的后缀
*
* @param file 表单⽂件
* @return后缀名
*/
public static final String getExtension(MultipartFile file) {
String fileName = OriginalFilename();
String extension = null;
if (fileName == null) {
return null;
} else {
int index = indexOfExtension(fileName);
extension = index == -1 ? "" : fileName.substring(index + 1);
}
if (StringUtils.isEmpty(extension)) {
extension = ContentType());
}
return extension;
}
public static int indexOfLastSeparator(String filename) {
if (filename == null) {
return -1;
} else {
int lastUnixPos = filename.lastIndexOf(47);
int lastWindowsPos = filename.lastIndexOf(92);
return Math.max(lastUnixPos, lastWindowsPos);
}
}
public static int indexOfExtension(String filename) {
if (filename == null) {
return -1;
} else {
int extensionPos = filename.lastIndexOf(46);
int lastSeparator = indexOfLastSeparator(filename);
return lastSeparator > extensionPos ? -1 : extensionPos;
}
}
public void setDEFAULT_BASE_FILE(String DEFAULT_BASE_FILE) {
FileUploadUtils.DEFAULT_BASE_FILE = DEFAULT_BASE_FILE;
}
public String getDEFAULT_BASE_FILE() {
return DEFAULT_BASE_FILE;
}
}
FileUtils
******⽂件下载需要⽤到这边的writeByte
主要功能:删除⽂件、⽂件名校验、⽂件下载时进⾏字节流写⼊
public class FileUtils {
/
/⽂件名正则校验
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+"; public static void writeBytes(String filePath, OutputStream os) {
FileInputStream fi = null;
try {
File file = new File(filePath);
if (!ists()) {
throw new FileNotFoundException(filePath);
}
fi = new FileInputStream(file);
byte[] b = new byte[1024];
int length;
while ((length = fi.read(b)) > 0) {
os.write(b, 0, length);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(os != null) {
try {
os.close();
}catch (IOException e) {
e.printStackTrace();
}
}
if(fi != null) {
try {
fi.close();
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
/
**
* 删除⽂件
* @param filePath ⽂件路径
* @return是否成功
*/
public static boolean deleteFile(String filePath) {
boolean flag = false;
File file = new File(filePath);
if (file.isFile() && ists()) {
file.delete();
flag = true;
}
return flag;
}
/**
* ⽂件名校验
* @param fileName ⽂件名
* @return true 正常, false ⾮法
*/
public static boolean isValidName(String fileName) {
return fileName.matches(FILENAME_PATTERN);
}
/
**
* 下载⽂件名重新编码
*

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。