以前的文件上传都是之前前辈写的,现在自己来写一个,大家可以看看,有什么问题可以在评论中提出来。

写的这个文件上传是在spring boot 2.0中测试的,测试了,可以正常上传,下面贴代码

第一步:引入依赖

这里我用的是maven构建项目,spring boot 的相关pom我就不贴了,我这里贴我额外引入的。

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- Apache Commons FileUpload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<!-- Apache Commons IO -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<!-- thumbnailator 图片压缩工具 -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>

第二步:编写上传返回结果实体 FileResult.java

import lombok.Data;

/**
* 文件上传返回的数据实体
*
* @author lixingwu
*/
@Data
public class FileResult {
// 文件名
private String fileName;
   // 扩展名
private String extName;
   // 文件大小,字节
private Long fileSize;
   // 文件存储在服务器的相对地址
private String serverPath;
}

第三步:编写 PropertiesUtils.java 和 custom.properties

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties; /**
* 读取properties文件
*
* @author lixingwu
*/
public class PropertiesUtils {
private Properties properties;
private static PropertiesUtils propertiesUtils = new PropertiesUtils(); /**
* 私有构造,禁止直接创建
*/
private PropertiesUtils() {
properties = new Properties();
InputStream in = PropertiesUtils.class.getClassLoader()
.getResourceAsStream("custom.properties");
try {
properties.load(in);
} catch (IOException e) {
e.printStackTrace();
}
} /**
* 获取单例
*
* @return PropertiesUtils
*/
public static PropertiesUtils getInstance() {
if (propertiesUtils == null) {
propertiesUtils = new PropertiesUtils();
}
return propertiesUtils;
} /**
* 根据属性名读取值
*
* @param name 名称
*/
public Object getProperty(String name) {
return properties.getProperty(name);
} /*************************************************************************/
/*****************************读取属性,封装字段**************************/
/*************************************************************************/ /**
* 是否调试模式
*/
public Boolean isDebug() {
return "true".equals(properties.getProperty("isDebug"));
} public String getAttachmentServer() {
return properties.getProperty("attachmentServer");
} public String getAttachmentPath() {
return properties.getProperty("attachmentPath");
} public String getAttachmentGainPpath() {
return properties.getProperty("attachmentGainPath");
} public static void main(String[] args) {
PropertiesUtils pro = PropertiesUtils.getInstance();
String value = String.valueOf(pro.getProperty("custom.properties.name").toString());
System.out.println(value);
}
}

custom.properties(具体路径,根据自己项目进行修改)

# 自定义 属性文件,可使用 PropertiesUtils.java 来读取
custom.properties.name=custom.properties
isDebug=true #附件地址
attachmentServer=www.baidu.con/static #服务器静态文件地址
attachmentPath=/var/www/html #服务器存储文件的地址
attachmentGainPath=/var/www/html/upload

第四步:编写 FileuploadUtil.java

package com.zhwlt.logistics.utils;

import com.zhwlt.logistics.pojo.system.FileResult;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile; import java.io.File;
import java.io.IOException;
import java.util.*; /**
* 文件上传工具类(修改了bug 2019-0105)
*
* @author lixingwu
*/
public class FileuploadUtil { /**
* 属性配置
*/
private static PropertiesUtils pro = PropertiesUtils.getInstance(); /**
* 方法描述:根据文件的绝对路径创建一个文件对象.
* 创建时间:2018-10-19 09:32:34
*
* @param filePath 文件的绝对路径
* @return 返回创建的这个文件对象
* @author "lixingwu"
*/
public static File createFile(String filePath) throws IOException {
// 获取文件的完整目录
String fileDir = FilenameUtils.getFullPath(filePath);
// 判断目录是否存在,不存在就创建一个目录
File file = new File(fileDir);
if (!file.isDirectory()) {
//创建失败返回null
if (!file.mkdirs()) {
throw new IOException("文件目录创建失败...");
}
}
// 判断这个文件是否存在,不存在就创建
file = new File(filePath);
if (!file.exists()) {
if (!file.createNewFile()) {
throw new IOException("目标文件创建失败...");
}
}
return file;
} /**
* 方法描述:判断extension中是否存在extName
* 创建时间:2018-10-20 20:46:18
*
* @param extension 使用逗号隔开的字符串,精确匹配例如:txt,jpg,png,zip
* @param extName 文件的后缀名
* @author "lixingwu"
*/
private static void isContains(String extension, String extName) {
if (StringUtils.isNotEmpty(extension)) {
// 切割文件扩展名
String[] exts = StringUtils.split(extension, ",");
if (ArrayUtils.isNotEmpty(exts)) {
assert exts != null;
List<String> extList = Arrays.asList(exts);
//判断
if (!extList.contains(extName)) {
throw new RuntimeException("上传文件的类型只能是:" + extension);
}
} else {
// 判断文件的后缀名是否为extension
if (!extension.equalsIgnoreCase(extName)) {
throw new RuntimeException("上传文件的类型只能是:" + extension);
}
}
}
} /**
* 方法描述:处理上传的图片
* 创建时间:2018-10-20 20:46:18
*
* @param serverPath 图片的绝对路径
* @param childFile 子文件夹
* @param extName 文件的后缀
* @author "lixingwu"
*/
private static String thumbnails(String serverPath, String childFile, String extName)
throws IOException {
// 压缩后的相对路径文件名
String toFilePath = getDestPath(childFile, extName); // scale:图片缩放比例
// outputQuality:图片压缩比例
// toFile:图片位置
// outputFormat:文件输出后缀名
// Thumbnails 如果用来压缩 png 格式的文件,会越压越大,
// 得把png格式的图片转换为jpg格式
if ("png".equalsIgnoreCase(extName)) {
// 由于outputFormat会自动在路径后加上后缀名,所以移除以前的后缀名
String removeExtensionFilePath = FilenameUtils.removeExtension(toFilePath);
Thumbnails.of(serverPath).scale(1f)
.outputQuality(0.5f)
.outputFormat("jpg")
.toFile(getServerPath(removeExtensionFilePath));
toFilePath = removeExtensionFilePath + ".jpg";
} else {
Thumbnails.of(serverPath).scale(1f).outputQuality(0.5f)
.toFile(getServerPath(toFilePath));
} // 删除被压缩的文件
FileUtils.forceDelete(new File(serverPath)); return toFilePath;
} /**
* 方法描述:生成文件文件名
* 创建时间:2018-10-20 20:46:18
*
* @param childFile 子目录
* @param extName 后缀名
* @author "lixingwu"
*/
private static String getDestPath(String childFile, String extName) {
//规则: 子目录/年月日_随机数.后缀名
String sb = childFile + "/"
+ DateUtil.formatDate(new Date(), DateUtil.DATE_FORMAT_SHORT)
+ "_" + Tools.getRandom()
+ "." + extName;
return sb;
} /**
* 方法描述:生成文件在的实际的路径
* 创建时间:2018-10-20 20:46:18
*
* @param destPath 文件的相对路径
* @author "lixingwu"
*/
private static String getServerPath(String destPath) {
// 文件分隔符转化为当前系统的格式
return FilenameUtils.separatorsToSystem(pro.getAttachmentGainPpath() + destPath);
} /**
* 方法描述:上传文件.
* 创建时间:2018-10-19 13:09:19
*
* @param multipartFile 上传的文件对象,必传
* @param childFile 上传的父目录,为空直接上传到指定目录 (会在指定的目录下新建该目录,例如:/user/1023)
* @param extension 允许上传的文件后缀名,为空不限定上传的文件类型 (使用逗号隔开的字符串,精确匹配例如:txt,jpg,png,zip)
* @param isImage 上传的是否是图片,如果是就会进行图片压缩;如果不希望图片被压缩,则传false,让其以文件的形式来保存
* @return the file result
* @throws IOException 异常信息应返回
* @author "lixingwu"
*/
private static FileResult saveFile(MultipartFile multipartFile, String childFile, String extension, Boolean isImage) throws IOException {
if (null == multipartFile || multipartFile.isEmpty()) {
throw new IOException("上传的文件对象不存在...");
}
// 文件名
String fileName = multipartFile.getOriginalFilename();
// 文件后缀名
String extName = FilenameUtils.getExtension(fileName);
if (StringUtils.isEmpty(extName)) {
throw new RuntimeException("文件类型未定义不能上传...");
}
// 判断文件的后缀名是否符合规则
isContains(extension, extName);
// 创建目标文件的名称,规则请看destPath方法
String destPath = getDestPath(childFile, extName);
// 文件的实际路径
String serverPath = getServerPath(destPath);
// 创建文件
File destFile = createFile(serverPath);
// 保存文件
multipartFile.transferTo(destFile); // 拼装返回的数据
FileResult result = new FileResult();
//如果是图片,就进行图片处理
if (BooleanUtils.isTrue(isImage)) {
// 图片处理
String toFilePath = thumbnails(serverPath, childFile, extName);
// 得到处理后的图片文件对象
File file = new File(getServerPath(toFilePath));
// 压缩后的文件后缀名
String extExtName = FilenameUtils.getExtension(toFilePath);
// 源文件=源文件名.压缩后的后缀名
String extFileName = FilenameUtils.getBaseName(fileName) + "." + FilenameUtils.getExtension(toFilePath);
result.setFileSize(file.length());
result.setServerPath(toFilePath);
result.setFileName(extFileName);
result.setExtName(extExtName);
} else {
result.setFileSize(multipartFile.getSize());
result.setFileName(fileName);
result.setExtName(extName);
result.setServerPath(destPath);
}
return result;
} /**
* 方法描述:上传文件.
* 创建时间:2018-10-19 13:09:19
*
* @param multipartFile 上传的文件对象,必传
* @param childFile 上传的父目录,为空直接上传到指定目录 (会在指定的目录下新建该目录,例如:/user/1023)
* @param extension 允许上传的文件后缀名,为空不限定上传的文件类型 (使用逗号隔开的字符串,精确匹配例如:txt,jpg,png,zip)
* @return the file result
* @throws IOException 异常信息应返回
* @author "lixingwu"
*/
public static FileResult saveFile(MultipartFile multipartFile, String childFile, String extension) throws IOException {
return saveFile(multipartFile, childFile, extension, false);
} /**
* 方法描述:上传图片.
* 创建时间:2018-10-19 13:09:19
*
* @param multipartFile 上传的文件对象,必传
* @param childFile 上传的父目录,为空直接上传到指定目录 (会在指定的目录下新建该目录,例如:/user/1023)
* @param extension 允许上传的文件后缀名,为空不限定上传的文件类型 (使用逗号隔开的字符串,精确匹配例如:txt,jpg,png,zip)
* @return the file result
* @throws IOException 异常信息应返回
* @author "lixingwu"
*/
public static FileResult saveImage(MultipartFile multipartFile, String childFile, String extension) throws IOException {
return saveFile(multipartFile, childFile, extension, true);
} }

第五步:编写 UploadCtl.java (测试可用 Postman)

package com.zhwlt.logistics.controller.system;

import com.zhwlt.logistics.controller.base.BaseController;
import com.zhwlt.logistics.pojo.system.CommonResult;
import com.zhwlt.logistics.utils.FileuploadUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import java.io.IOException; /**
* 上传文件
*
* @author lixingwu
*/
@RestController
@RequestMapping("/system")
@Api(description = "上传文件类", tags = {"UploadCtl"})
public class UploadCtl extends BaseController{ /**
* 方法描述:文件上传,图片也可以使用,但是图片不会被压缩.
* 创建时间:2018-10-19 14:10:32
*
* @param childFile 上传的父目录
* @param extension 允许上传的文件后缀名
* @author "lixingwu"
*/
@ApiOperation(value = "文件上传", notes = "图片也可以使用,但是图片不会被压缩")
@PostMapping("/uploadFile")
public CommonResult uploadFile(
MultipartFile multipart,
@RequestParam(value = "childFile", required = false, defaultValue = "") String childFile,
@RequestParam(value = "extension", required = false, defaultValue = "") String extension
) throws IOException {
return resultDataWrapper(FileuploadUtil.saveFile(multipart, childFile, extension));
} /**
* 方法描述:图片上传,只能给图片使用,其他文件调用会异常.
* 创建时间:2018-10-19 14:10:32
*
* @param childFile 上传的父目录
* @param extension 允许上传的文件后缀名
* @author "lixingwu"
*/
@ApiOperation(value = "图片上传", notes = "只能给图片使用,其他文件调用会异常")
@PostMapping("/uploadImage")
public CommonResult uploadImage(
MultipartFile multipart,
@RequestParam(value = "childFile", required = false, defaultValue = "") String childFile,
@RequestParam(value = "extension", required = false, defaultValue = "") String extension
) throws IOException {
return resultDataWrapper(FileuploadUtil.saveImage(multipart, childFile, extension));
} }

spring boot 文件上传工具类(bug 已修改)的更多相关文章

  1. spring mvc 文件上传工具类

    虽然文件上传在框架中,已经不是什么困难的事情了,但自己还是开发了一个文件上传工具类,是基于springmvc文件上传的. 工具类只需要传入需要的两个参数,就可以上传到任何想要上传的路径: 参数1:Ht ...

  2. Spring Boot 文件上传原理

    首先我们要知道什么是Spring Boot,这里简单说一下,Spring Boot可以看作是一个框架中的框架--->集成了各种框架,像security.jpa.data.cloud等等,它无须关 ...

  3. 文件上传工具类 UploadUtil.java

    package com.util; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import ja ...

  4. FastDFS 文件上传工具类

    FastDFS文件上传工具类 import org.csource.common.NameValuePair; import org.csource.fastdfs.ClientGlobal; imp ...

  5. spring boot文件上传、下载

    主题:Spring boot 文件上传(多文件上传)[从零开始学Spring Boot]http://www.iteye.com/topic/1143595 Spring MVC实现文件下载http: ...

  6. Spring Boot 文件上传简易教程

    上传文件是我们日常使用最为广泛的功能之一,比如App端上传头像.本章演示如何从客户端上传到 Spring Boot 开发的 Api中. 本项目源码 github 下载 1 新建 Spring Boot ...

  7. spring boot 文件上传大小限制

    错误信息 : Spring Boot:The field file exceeds its maximum permitted size of 1048576 bytes. 解决方法一:在启动类添加如 ...

  8. Spring Boot 文件上传与下载

    原文地址: https://www.cnblogs.com/studyDetail/p/7003253.html 1.在pom.xml文件中添加依赖 <project xmlns="h ...

  9. (29)Spring boot 文件上传(多文件上传)【从零开始学Spring Boot】

    文件上传主要分以下几个步骤: (1)新建maven java project: (2)在pom.xml加入相应依赖: (3)新建一个表单页面(这里使用thymleaf); (4)编写controlle ...

随机推荐

  1. 【Java编程思想读书笔记】继承中父类的初始化方式

    继承中父类的初始化方式 p144页有感 一.提出问题 假设有一些类,这些类有继承关系的时候,当初始化一个子类对象,对于该类的父类而言,发生了什么呢?是仅仅只是复制了一个引用还是也会同时new一个父类对 ...

  2. Android中TimePicker时间选择器的使用和获取选择的时和分

    场景 实现效果如下 注: 博客: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关电子书.教程推送与免费下载. 实现 将布局改 ...

  3. 【JZOJ 5048】【GDOI2017模拟一试4.11】IQ测试

    题目大意: 判断一个序列是否是另外一个序列删除若干个数字之后得到的. 正文: 我们可以定义两个指针,分别指向长序列和短序列. 拿样例来举例: 如果指针指的数相同,两个指针都往右跳: 如果不同,则指向长 ...

  4. .net core 中api 模型验证

    AddControllers/AddMvc方法允许添加自定义ActionFilterAttribute进行过滤 文档中这么定义Filter: 可以创建自定义筛选器,用于处理横切关注点. 横切关注点的示 ...

  5. JavaWeb学生公寓(宿舍)管理系统源码

    开发环境: Windows操作系统开发工具: MyEclipse+Jdk+Tomcat+MySQL数据库 运行效果图 源码及原文链接:https://javadao.xyz/forum.php?mod ...

  6. Html介绍,认识html文件基本结构

    一个HTML文件的基本机构如下: <html><head>...</head><body>...</body></html>代码 ...

  7. Android在Activity中与Fragment中创建自定义菜单的区别

    区别就在这里,Activity中添加菜单要这样: public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R ...

  8. VMvare桥接网络连接不上解决办法

    记一次学习中的突发状况.由于本人的pc时长要在不同的网络中进行切换,ip地址一般都是不固定的,所以我使用虚拟机的时候一般使用的都是让VMvare自动识别网络环境.直到今天遇到一种突发情况,VMvare ...

  9. 字段类型(uniqueidentifier)问题

    环境:SQL 2016: 语句 select * from A where PID=JoID 上述查询语句中的Where PID=JoID条件中PID的字段类型为varchar(50)而JoID的字段 ...

  10. c#中用office组件读取excel时提示异常来自 HRESULT:0x80010105 (RPC_E_SERVERFAULT)

    在excel2007,找到“excel选项”,点开后点击“加载项”,最下面有个管理加载项的下拉菜单,选“COM加载项”,点“转到”,这时会弹出一个框,把里面pdf软件的加载项前面的勾去掉,点确定就ok ...