1.依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!--谷歌图片压缩组件-->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
</dependencies>
2.配置文件
server.port=80
spring.aop.proxy-target-class=true
server.tomcat.uri-encoding=utf-8
spring.datasource.qy.name=qy
spring.datasource.qy.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.qy.url=jdbc\:mysql\://ip\:port/scm11?useUnicode\=true&characterEncoding\=utf-8&zeroDateTimeBehavior\=round&transformedBitIsBoolean\=true&useSSL\=false&allowMultiQueries\=true
spring.datasource.qy.username=root
spring.datasource.qy.password=password
spring.datasource.fqy.name=fqy
spring.datasource.fqy.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.fqy.url=jdbc\:mysql\://ip\:port/scm12?useUnicode\=true&characterEncoding\=utf-8&zeroDateTimeBehavior\=round&transformedBitIsBoolean\=true&useSSL\=false&allowMultiQueries\=true
spring.datasource.fqy.username=root
spring.datasource.fqy.password=password
#显示sql语句
spring.jpa.show-sql=true
spring.data.mongodb.uri=mongodb\://root\:sql666@ip\:port/admin
spring.data.mongodb.database=chenfan_photo_test
spring.servlet.multipart.max-file-size: 2048Mb
spring.servlet.multipart.max-request-size: 200Mb
spring.servlet.multipart.resolve-lazily: true
3.枚举类,返回体代码
public enum ResponseCode {
/** 成功 */
SUCCESS(200, "success"),
/** 保存成功 */
SAVE_SUCCESS(200, "保存成功"),
/** 保存失败 */
SAVE_ERROR(500, "保存失败"),
/** 删除成功*/
DELETE_SUCCESS(200, "删除成功"),
/** 删除失败*/
DELETE_ERROR(500, "删除失败"),
/** 获取数据库连接失败 */
NOT_FIND_DATABASE_CONN(401, "not find database conn"),
LOGIN_SUCCESS(200, "登陆成功"),
LOGIN_ERROR(401, "登陆失败"),
LOGIN_EASY(500, "登陆密码过于简单"),
PARAMETER_ERROR(403,"参数错误"),
SAMPLE_STOCK_HANDOVER_ERROR(400,"此样衣正在转交中"),
STOCKOUT_ERROR(400,"库存不足,请修改后提交");
private final int code;
private final String msg;
ResponseCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
public class Constant {
/** 参数错误 */
public static final int ERROR_PARAM_CODE = 400;
/** 登陆错误 */
public static final int UN_AUTHORIZED = 401;
/** 操作失败 */
public static final int FAIL = 401;
/** 非预期性内部错误 */
public static final int EXCEPTION = 500;
/** 业务异常 */
public static final int ERROR_BUSINESS_CODE = 501;
/** 数据源类型 */
public static final String DATA_TYPE = "dataType";
/** 返回数据格式,json */
public static final String CONTENT_TYPE = "application/json; charset=utf-8";
/** user信息 */
public static final String USER_INFO = "user_info";
/** token */
public static final String AUTHORIZATION_TOKEN = "Authorization";
/** agent */
public static final String USER_AGENT = "user_agent";
/** user_session_id */
public static final String USER_SESSION_ID = "uid";
public static final String AUTHORIZATION = "userToken";
public static final String HEADER_IP = "user_ip";
public static final String ANDROID_AGENT = "Android";
public static final String TOKEN_PIC_CODE = "verifyCodeToken";
private Constant() {}
}
@ApiModel
@Data
public class Response<T> {
/** 返回码 */
@ApiModelProperty(position = 1, value = "返回码")
private int code;
/** 返回文字内容 */
@ApiModelProperty(position = 2, value = "返回信息")
private String message;
/** 返回实体对象 */
@ApiModelProperty(position = 3, value = "返回体")
private T obj;
public Response(int code, String message, T obj) {
this.code = code;
this.message = message;
this.obj = obj;
}
public Response() {}
public Response(Exception ex) {
this.code = Constant.EXCEPTION;
this.message = ex.getMessage();
}
public Response(int code, String message) {
this.code = code;
this.message = message;
}
public Response(ResponseCode responseCode) {
this.code = responseCode.getCode();
this.message = responseCode.getMsg();
}
public Response(ResponseCode responseCode, T obj) {
this.code = responseCode.getCode();
this.message = responseCode.getMsg();
this.obj = obj;
}
}
4.文件上传
//文件上传的返回值
@Data
public class FileResult {
private String fileName;
private String id;
}
@RestController
@RequestMapping("file/")
@Slf4j
public class FileController {
@Autowired
private FileService fileService;
@ApiOperation(value = "上传文件", notes = "上传文件")
@PostMapping(value = "upload")
public Response<Object> upload(MultipartHttpServletRequest request) {
log.info("进入方法>>>--upload--上传文件");
if (null != request) {
List<FileResult> upload = null;
try {
upload = fileService.upload(request);
} catch (Exception e) {
log.error(e.getMessage(), e);
return new Response<>(Constant.EXCEPTION, e.getMessage());
}
log.info("退出方法>>>--upload--上传文件");
return new Response<>(ResponseCode.SUCCESS, upload);
}
log.info("退出方法>>>--upload--上传文件");
return new Response<>(Constant.FAIL, "上传文件不能为空");
}
}
@Service
@Slf4j
public class FileService {
@Autowired
private FileMapper fileMapper;
private static final String[] FILE_TYPES =
new String[] {
"jpg", "bmp", "jpeg", "png", "gif", "tif", "pcx", "tga", "exif", "exif", "svg",
"psd", "cdr", "pcd", "dxf", "ufo", "eps", "ai", "raw", "WMF", "webp"
};
public List<FileResult> upload(MultipartHttpServletRequest request) {
List<FileResult> result = new ArrayList<>();
//拿到文件名
Iterator<String> fileNames = request.getFileNames();
while (fileNames.hasNext()) {
FileResult fileResult = new FileResult();
String fileName = fileNames.next();
//根据文件名拿到文件
MultipartFile file = request.getFile(fileName);
//获取上传文件的原名
String name = file.getOriginalFilename();
String fileNameStr= Base64.encodeBase64String(name.getBytes());
String[] split = name.split("\\.");
//拿到文件后缀名
String suff = split[split.length - 1];
// 文件类型
String contentType = file.getContentType();
String save = "";
try {
save = fileMapper.save(file.getInputStream(), fileNameStr, contentType);
} catch (IOException e) {
e.printStackTrace();
log.error(e.getMessage());
}
if (null != save) {
fileResult.setFileName(name);
fileResult.setId(save + "." + suff);
}
result.add(fileResult);
}
return result;
}
}
@Component
public class FileMapper {
@Autowired
private GridFsTemplate gridFsTemplate;
public String save(InputStream file, String fileName, String contentType) {
// 将文件存储到mongodb中,mongodb 将会返回这个文件的具体信息
ObjectId store = gridFsTemplate.store(file, fileName, contentType);
String id = store.toString();
if (StringUtils.hasLength(id)) {
return id;
}
return null;
}
}
上传成功
5.文件下载
@ApiOperation(value = "下载文件", notes = "下载文件")
@GetMapping(value = "download")
public Response<Object> download(String fileId, HttpServletResponse response) {
log.info("进入方法>>>--download--下载文件");
if (!StringUtils.hasLength(fileId)) {
return new Response<>(Constant.ERROR_PARAM_CODE, "文件ID不能为空");
}
String[] split = fileId.split("\\.");
try {
fileService.download(split[0], response);
} catch (Exception e) {
log.error(e.getMessage(), e);
return new Response<>(Constant.EXCEPTION, e.getMessage());
}
log.info("退出方法>>>--download--下载文件");
return new Response<>(ResponseCode.SUCCESS);
}
@Component
public class FileMapper {
@Autowired
private GridFsTemplate gridFsTemplate;
public String save(InputStream file, String fileName, String contentType) {
// 将文件存储到mongodb中,mongodb 将会返回这个文件的具体信息
ObjectId store = gridFsTemplate.store(file, fileName, contentType);
String id = store.toString();
if (StringUtils.hasLength(id)) {
return id;
}
return null;
}
public GridFSFile find(String fileId) {
return gridFsTemplate.findOne(Query.query(Criteria.where("_id").is(fileId)));
}
}
public void download(String fileId, HttpServletResponse response) {
if (!StringUtils.hasLength(fileId)) {
throw new RuntimeException("ID不能为空");
}
GridFSFile file = fileMapper.find(fileId);
if (null == file) {
throw new RuntimeException("ID对应文件不存在");
}
String fileName = file.getFilename();
String[] split = fileName.split("\\.");
try {
Long.parseLong(split[0]);
} catch (Exception e) {
fileName =
new String(
Base64.decodeBase64(fileName.getBytes(StandardCharsets.UTF_8)),
StandardCharsets.UTF_8);
}
//转成GridFsResource类取文件类型
response.setContentType(mongoResource.convertGridFSFile2Resource(file).getContentType());
response.setHeader("Content-Disposition", "attachment; filename=" +fileName);
//文件长度
response.setHeader("Content-Length", String.valueOf(file.getLength()));
try {
OutputStream out = response.getOutputStream();
//IO复制
InputStream in=mongoResource.convertGridFSFile2Resource(file).getInputStream();
IOUtils.copy(
mongoResource.convertGridFSFile2Resource(file).getInputStream(), out);
} catch (IOException e) {
log.error(e.getMessage());
}
log.info("文件传输完成,退出方法");
}
下载成功,切记不要用swagger接口去下载,会乱码;
下载成功返回值为null,关闭outputstream后不能再返回值
6.图片查看
@ApiOperation(value = "读取图片--压缩", notes = "读取图片")
@GetMapping(value = "views/{id}")
public void viewsImg(
@PathVariable String id, HttpServletRequest request, HttpServletResponse response)
throws Exception {
log.info("进入方法>>>--viewsImg--读取图片");
if (id != null && !"null".equalsIgnoreCase(id)) {
try {
fileService.viewImg(id, request, response);
} catch (IOException e) {
log.error("读取图片文件失败", e.getMessage(), e);
log.info("退出方法>>>--viewsImg--读取图片");
}
log.info("退出方法>>>--viewsImg--读取图片");
} else {
log.info("退出方法>>>--viewsImg--读取图片>没有文件id");
}
}
public void viewImg(String id, HttpServletRequest request, HttpServletResponse response) throws IOException {
// 因为取出来的id带有后缀,因此做去除后缀处理
if (id.contains(".")) {
String[] split = id.split("\\.");
id = split[0];
}
GridFSFile file = fileMapper.find(id);
if (null == file) {
throw new RuntimeException("ID对应文件不存在");
}
String fileName = file.getFilename();
String[] split = fileName.split("\\.");
try {
Long.parseLong(split[0]);
} catch (Exception e) {
fileName =
new String(
Base64.decodeBase64(fileName.getBytes(StandardCharsets.UTF_8)),
StandardCharsets.UTF_8);
}
OutputStream out = response.getOutputStream();
//取后缀
String sub = fileName.substring(fileName.lastIndexOf(".") + 1);
boolean flag = false;
for (String fileType : FILE_TYPES) {
if (sub.equalsIgnoreCase(fileType)) {
flag = true;
break;
}
}
if (flag) {
log.info("图片类型,进入预览");
response.setHeader("Content-disposition", "inline; filename=" + fileName);
response.setContentType("image/" + sub);
// 不进行压缩的文件大小,单位为bit
int notCompressionBit = 512000;
//大于512000bit就压缩
if (file.getLength() > notCompressionBit) {
Thumbnails.of(mongoResource.convertGridFSFile2Resource(file).getInputStream())
.scale(0.2f)
.outputQuality(0.5f)
.toOutputStream(out);
}
out.flush();
out.close();
} else {
log.info("非图片类型,进入下载");
//转成GridFsResource类取文件类型
response.setContentType(mongoResource.convertGridFSFile2Resource(file).getContentType());
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
//文件长度
response.setHeader("Content-Length", String.valueOf(file.getLength()));
try {
//IO复制
InputStream in = mongoResource.convertGridFSFile2Resource(file).getInputStream();
IOUtils.copy(
mongoResource.convertGridFSFile2Resource(file).getInputStream(), out);
} catch (IOException e) {
log.error(e.getMessage());
}
}
}
7.批量下载压缩文件
@ApiOperation(value = "批量下载压缩文件", notes = "批量下载压缩文件")
@GetMapping(value = "downloadToZip")
public Response<Object> downloadToZip(
String zipName,
String fileIds,
HttpServletRequest request,
HttpServletResponse response) {
log.info("进入方法>>>--downloadToZip--批量下载压缩文件");
if (!StringUtils.hasLength(fileIds)) {
return new Response<>(Constant.ERROR_PARAM_CODE, "文件ID不能为空");
}
try {
fileService.downloadToZip(zipName, fileIds, request, response);
} catch (Exception e) {
log.error(e.getMessage(), e);
log.info("退出方法>>>--downloadToZip--批量下载压缩文件");
return new Response<>(Constant.EXCEPTION, e.getMessage());
}
log.info("退出方法>>>--downloadToZip--批量下载压缩文件");
return new Response<>(ResponseCode.SUCCESS);
}
public void downloadToZip(
String zipName,
String fileIds,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
//压缩包文件名
zipName = new String(zipName.getBytes("ISO8859-1"), "UTF-8"); // 转换文件名,防止乱码
// 获得请求头中的User-Agent
String agent = request.getHeader("User-Agent");
// 根据不同的客户端进行不同的编码
if (agent.contains("MSIE")) {
// IE浏览器
zipName = URLEncoder.encode(zipName, "utf-8");
zipName = zipName.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
zipName = "=?utf-8?B?" + base64Encoder.encode(zipName.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器
zipName = URLEncoder.encode(zipName, "utf-8");
}
// 初始化信息
response.setContentType("application/zip");
response.setHeader("Content-disposition", "attachment; filename=" + zipName);
ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream());
// 获取文件信息
String[] fileIdsArray = fileIds.split("\\;");
for (int i = 0; i < fileIdsArray.length; i++) {
String[] fileIdArray = fileIdsArray[i].split("\\.");
if (!StringUtils.hasLength(fileIdArray[0])) {
throw new RuntimeException("ID不能为空");
}
GridFSFile file = fileMapper.find(fileIdArray[0]);
if (null == file) {
throw new RuntimeException("ID对应文件不存在");
}
String fileName = file.getFilename();
String[] split = fileName.split("\\.");
try {
Long.parseLong(split[0]);
} catch (Exception e) {
fileName =
new String(
Base64.decodeBase64(fileName.getBytes(StandardCharsets.UTF_8)),
StandardCharsets.UTF_8);
}
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
IOUtils.copy(mongoResource.convertGridFSFile2Resource(file).getInputStream(), byteOut);
byte[] data = byteOut.toByteArray();
zipOut.putNextEntry(new ZipEntry(fileName));
zipOut.write(data);
zipOut.closeEntry();
byteOut.close();
}
zipOut.flush();
zipOut.close();
log.info("文件传输完成,退出方法");
}