Commit 96333f80 authored by huangcb's avatar huangcb

新增接口:图片水印合成功能接口

parent 6f362df5
package com.esv.freight.file.common.component;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* @description:
* @project: freight-file-service
* @name: com.esv.freight.file.common.component.ApplicationLoadRunner
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/05/28 14:33
* @version:1.0
*/
@Slf4j
@Component
public class ApplicationLoadRunner implements ApplicationRunner {
@Value("${spring.application.name}")
private String applicationName;
@Override
public void run(ApplicationArguments var) {
log.info("-------------------- [{}]初始化完成 --------------------", applicationName);
}
}
\ No newline at end of file
...@@ -84,20 +84,20 @@ public class RestLogFilter implements Filter { ...@@ -84,20 +84,20 @@ public class RestLogFilter implements Filter {
bodyStr = sb.toString(); bodyStr = sb.toString();
} }
} catch (IOException e) { } catch (IOException e) {
log.error("解析post参数时发生错误:{}", e.getMessage()); log.error("解析post参数时发生错误:{}", e.getMessage(), e);
} finally { } finally {
if (inputStream != null) { if (inputStream != null) {
try { try {
inputStream.close(); inputStream.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); log.error(e.getMessage(), e);
} }
} }
if (reader != null) { if (reader != null) {
try { try {
reader.close(); reader.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); log.error(e.getMessage(), e);
} }
} }
} }
......
package com.esv.freight.file.module.file.controller; package com.esv.freight.file.module.file.controller;
import com.alibaba.fastjson.JSONObject;
import com.esv.freight.file.common.exception.EException; import com.esv.freight.file.common.exception.EException;
import com.esv.freight.file.common.response.EResponse; import com.esv.freight.file.common.response.EResponse;
import com.esv.freight.file.common.validator.groups.ValidatorInsert; import com.esv.freight.file.common.validator.groups.ValidatorInsert;
import com.esv.freight.file.module.file.form.FileForm; import com.esv.freight.file.module.file.form.FileForm;
import com.esv.freight.file.module.file.service.FileMetaService; import com.esv.freight.file.module.file.service.FileMetaService;
import com.esv.freight.file.module.file.service.FileService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.Base64;
/** /**
* @description: 文件上传Controller * @description: 文件上传Controller
* @project: freight-file-service * @project: freight-file-service
...@@ -30,17 +26,15 @@ import java.util.Base64; ...@@ -30,17 +26,15 @@ import java.util.Base64;
@Slf4j @Slf4j
@RestController @RestController
@RequestMapping("/upload") @RequestMapping("/upload")
@RefreshScope
public class UploadController { public class UploadController {
@Value("${file.register}")
private String FILE_REGISTER;
private FileMetaService fileMetaService; private FileMetaService fileMetaService;
private FileService fileService;
@Autowired @Autowired
public UploadController(FileMetaService fileMetaService) { public UploadController(FileMetaService fileMetaService, FileService fileService) {
this.fileMetaService = fileMetaService; this.fileMetaService = fileMetaService;
this.fileService = fileService;
} }
/** /**
...@@ -53,41 +47,9 @@ public class UploadController { ...@@ -53,41 +47,9 @@ public class UploadController {
@PostMapping("/single") @PostMapping("/single")
public EResponse uploadSingleFile(@RequestBody @Validated(ValidatorInsert.class) FileForm fileForm) throws EException { public EResponse uploadSingleFile(@RequestBody @Validated(ValidatorInsert.class) FileForm fileForm) throws EException {
// 校验文件类型及大小 // 校验文件类型及大小
checkFile(fileForm); fileService.checkFile(fileForm);
return EResponse.ok(fileMetaService.uploadFile(fileForm)); return EResponse.ok(fileMetaService.uploadFile(fileForm));
} }
/**
* description 校验文件类型及大小
* param []
* return java.lang.Boolean
* author Administrator
* createTime 2020/04/14 14:57
**/
void checkFile(FileForm fileForm) throws EException {
String[] types = FILE_REGISTER.trim().replaceAll(",", ",").split(",");
String type;
JSONObject fileTypeJson = new JSONObject();
for (int i = 0; i < types.length; i++) {
type = types[i];
fileTypeJson.put(type.split("=")[0], Integer.parseInt(type.split("=")[1]));
}
// 校验文件类型
String fileType = fileForm.getFileType();
if (!fileTypeJson.containsKey(fileType)) {
throw new EException(1001, "不支持的文件类型["+fileType+"]");
}
// 校验文件长度
String fileData = fileForm.getFileData();
byte[] bytes = Base64.getDecoder().decode(fileData);
int fileRegSize = fileTypeJson.getIntValue(fileType);
int fileMaxSize = fileRegSize * 1024 * 1024;
if (fileMaxSize < bytes.length) {
throw new EException(1002, "文件大小不能超过["+fileRegSize+"MB]");
}
}
} }
package com.esv.freight.file.module.file.controller;
import com.esv.freight.file.common.exception.EException;
import com.esv.freight.file.common.response.ECode;
import com.esv.freight.file.common.response.EResponse;
import com.esv.freight.file.common.validator.groups.ValidatorInsert;
import com.esv.freight.file.module.file.form.FileForm;
import com.esv.freight.file.module.file.form.WaterMarkForm;
import com.esv.freight.file.module.file.service.FileMetaService;
import com.esv.freight.file.module.file.service.FileService;
import com.esv.freight.file.module.file.service.WatermarkService;
import com.esv.freight.file.module.file.vo.FileVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @description: 水印图片合成Controller
* @project: freight-file-service
* @name: com.esv.freight.file.module.file.controller.WatermarkController
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/05/28 14:48
* @version:1.0
*/
@Slf4j
@RestController
@RequestMapping("/upload")
@RefreshScope
public class WatermarkController {
private FileMetaService fileMetaService;
private FileService fileService;
private WatermarkService watermarkService;
@Autowired
public WatermarkController(FileMetaService fileMetaService, FileService fileService,
WatermarkService watermarkService) {
this.fileMetaService = fileMetaService;
this.fileService = fileService;
this.watermarkService = watermarkService;
}
/**
* description 图片水印合成
* param [form]
* return com.esv.freight.file.common.response.EResponse
* author HuangChaobin
* createTime 2020/05/28 14:58
**/
@PostMapping("/imageWithWatermark")
public EResponse imageWithWatermark(@RequestBody @Validated(ValidatorInsert.class) WaterMarkForm form) throws EException {
// 校验文件类型及大小
FileForm fileForm = new FileForm();
fileForm.setFileType("image");
fileForm.setFileData(form.getFileData());
fileForm.setFileName(form.getFileName());
fileService.checkFile(fileForm);
// 校验是否有效图片
fileService.checkIsImage(form.getFileData());
// 添加水印
try {
watermarkService.addWatermark2Image(form);
} catch (Exception e) {
log.error("图片添加文字时发生错误:{}", e.getMessage(), e);
throw new EException(ECode.SERVER_ERROR.code(), ECode.SERVER_ERROR.message());
}
// 保存文件及元信息
fileForm.setFileData(form.getFileData());
FileVO vo = fileMetaService.uploadFile(fileForm);
return EResponse.ok(vo);
}
}
package com.esv.freight.file.module.file.form;
import com.esv.freight.file.common.validator.groups.ValidatorInsert;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
/**
* @description:
* @project: freight-file-service
* @name: com.esv.freight.file.module.upload.form.WaterMarkForm
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/04/14 14:03
* @version:1.0
*/
@Data
public class WaterMarkForm {
@NotBlank(message = "参数fileData不能为空", groups = {ValidatorInsert.class})
private String fileData;
@Length(max = 50, message = "参数fileName长度不合法", groups = {ValidatorInsert.class})
@NotBlank(message = "参数fileName不能为空", groups = {ValidatorInsert.class})
private String fileName;
@NotBlank(message = "参数text不能为空", groups = {ValidatorInsert.class})
private String text;
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
}
}
package com.esv.freight.file.module.file.service;
import com.esv.freight.file.common.exception.EException;
import com.esv.freight.file.module.file.form.FileForm;
/**
* @description:
* @project: freight-file-service
* @name: com.esv.freight.file.module.file.service.FileService
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/05/28 14:49
* @version:1.0
*/
public interface FileService {
/**
* description 文件校验
* param [fileForm]
* return void
* author HuangChaobin
* createTime 2020/05/28 14:52
**/
void checkFile(FileForm fileForm) throws EException;
/**
* description 校验是否图片数据
* param [fileData]
* return void
* author HuangChaobin
* createTime 2020/05/28 15:34
**/
void checkIsImage(String fileData) throws EException;
}
package com.esv.freight.file.module.file.service;
import com.esv.freight.file.module.file.form.WaterMarkForm;
/**
* @description:
* @project: freight-file-service
* @name: com.esv.freight.file.module.file.service.WatermarkService
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/05/28 16:00
* @version:1.0
*/
public interface WatermarkService {
/**
* description 图片添加文字水印
* param [form]
* return void
* author HuangChaobin
* createTime 2020/05/28 16:01
**/
void addWatermark2Image(WaterMarkForm form) throws Exception;
}
...@@ -5,8 +5,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; ...@@ -5,8 +5,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.esv.freight.file.common.em.DbDeletedEnum; import com.esv.freight.file.common.em.DbDeletedEnum;
import com.esv.freight.file.common.exception.EException; import com.esv.freight.file.common.exception.EException;
import com.esv.freight.file.common.util.AESSecretUtils; import com.esv.freight.file.common.util.AESSecretUtils;
import com.esv.freight.file.module.file.em.FileTypeEnum;
import com.esv.freight.file.module.file.dao.FileMetaDao; import com.esv.freight.file.module.file.dao.FileMetaDao;
import com.esv.freight.file.module.file.em.FileTypeEnum;
import com.esv.freight.file.module.file.entity.FileMetaEntity; import com.esv.freight.file.module.file.entity.FileMetaEntity;
import com.esv.freight.file.module.file.form.FileForm; import com.esv.freight.file.module.file.form.FileForm;
import com.esv.freight.file.module.file.service.FileMetaService; import com.esv.freight.file.module.file.service.FileMetaService;
...@@ -78,8 +78,7 @@ public class FileMetaServiceImpl extends ServiceImpl<FileMetaDao, FileMetaEntity ...@@ -78,8 +78,7 @@ public class FileMetaServiceImpl extends ServiceImpl<FileMetaDao, FileMetaEntity
objectId = gridFsTemplate.store(inputStream, fileName, FileTypeEnum.getEnumByType(fileType).getContentType()); objectId = gridFsTemplate.store(inputStream, fileName, FileTypeEnum.getEnumByType(fileType).getContentType());
fileId = objectId.toString(); fileId = objectId.toString();
} catch (Exception e) { } catch (Exception e) {
log.error("存储文件数据时发生错误"); log.error("存储文件数据时发生错误:{}", e.getMessage(), e);
log.error(e.getMessage(), e);
throw new EException("存储文件数据时发生错误"); throw new EException("存储文件数据时发生错误");
} }
...@@ -93,15 +92,13 @@ public class FileMetaServiceImpl extends ServiceImpl<FileMetaDao, FileMetaEntity ...@@ -93,15 +92,13 @@ public class FileMetaServiceImpl extends ServiceImpl<FileMetaDao, FileMetaEntity
try { try {
this.baseMapper.insert(metaEntity); this.baseMapper.insert(metaEntity);
} catch (Exception e) { } catch (Exception e) {
log.error("存储文件元信息时发生错误"); log.error("存储文件元信息时发生错误:{}", e.getMessage(), e);
log.error(e.getMessage(), e);
// 删除MongoDB存储文件 // 删除MongoDB存储文件
try { try {
deleteMongoFile(fileId); deleteMongoFile(fileId);
} catch (Exception ex) { } catch (Exception ex) {
log.error("删除文件数据时发生错误,文件id={}", fileId); log.error("删除文件[id={}]数据时发生错误:{}", fileId, e.getMessage(), e);
log.error(e.getMessage(), e);
} }
throw new EException("存储文件元信息发生错误"); throw new EException("存储文件元信息发生错误");
...@@ -219,8 +216,7 @@ public class FileMetaServiceImpl extends ServiceImpl<FileMetaDao, FileMetaEntity ...@@ -219,8 +216,7 @@ public class FileMetaServiceImpl extends ServiceImpl<FileMetaDao, FileMetaEntity
try { try {
deleteMongoFile(fileId); deleteMongoFile(fileId);
} catch (Exception e) { } catch (Exception e) {
log.error("删除文件数据时发生错误,文件id={}", fileId); log.error("删除文件[id={}]数据时发生错误:{}", fileId, e.getMessage(), e);
log.error(e.getMessage(), e);
} }
} }
} }
......
package com.esv.freight.file.module.file.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.esv.freight.file.common.exception.EException;
import com.esv.freight.file.module.file.form.FileForm;
import com.esv.freight.file.module.file.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import javax.imageio.ImageIO;
import java.awt.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Base64;
/**
* @description:
* @project: freight-file-service
* @name: com.esv.freight.file.module.file.service.impl.FileServiceImpl
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/05/28 14:53
* @version:1.0
*/
@Service("fileService")
@Slf4j
@RefreshScope
public class FileServiceImpl implements FileService {
@Value("${file.register}")
private String FILE_REGISTER;
@Override
public void checkFile(FileForm fileForm) throws EException {
String[] types = FILE_REGISTER.trim().replaceAll(",", ",").split(",");
String type;
JSONObject fileTypeJson = new JSONObject();
for (int i = 0; i < types.length; i++) {
type = types[i];
fileTypeJson.put(type.split("=")[0], Integer.parseInt(type.split("=")[1]));
}
// 校验文件类型
String fileType = fileForm.getFileType();
if (!fileTypeJson.containsKey(fileType)) {
throw new EException(1001, "不支持的文件类型["+fileType+"]");
}
// 校验文件长度
String fileData = fileForm.getFileData();
byte[] bytes = Base64.getDecoder().decode(fileData);
int fileRegSize = fileTypeJson.getIntValue(fileType);
int fileMaxSize = fileRegSize * 1024 * 1024;
if (fileMaxSize < bytes.length) {
throw new EException(1002, "文件大小不能超过["+fileRegSize+"MB]");
}
}
@Override
public void checkIsImage(String fileData) throws EException {
byte[] bytes = Base64.getDecoder().decode(fileData);
Image image;
try {
image = ImageIO.read(new ByteArrayInputStream(bytes));
} catch (IOException e) {
throw new EException(1100, "不是有效图片");
}
if (null == image) {
throw new EException(1010, "不是有效图片");
}
}
}
package com.esv.freight.file.module.file.service.impl;
import com.esv.freight.file.module.file.form.WaterMarkForm;
import com.esv.freight.file.module.file.service.WatermarkService;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Service;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Base64;
/**
* @description:
* @project: freight-file-service
* @name: com.esv.freight.file.module.file.service.impl.WatermarkServiceImpl
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/05/28 16:01
* @version:1.0
*/
@Service("watermarkService")
public class WatermarkServiceImpl implements WatermarkService {
private static final String DEFAULT_FONT_PATH = "/font/迷你简大黑.TTF";
@Override
public void addWatermark2Image(WaterMarkForm form) throws Exception {
byte[] bytes = Base64.getDecoder().decode(form.getFileData());
Image image = ImageIO.read(new ByteArrayInputStream(bytes));
int imgWidth = image.getWidth(null);
int imgHeight = image.getHeight(null);
BufferedImage bufImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = bufImg.createGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
graphics2D.drawImage(image, 0, 0, imgWidth, imgHeight, null);
// 设置字体及颜色
Font font = getDefaultFont(DEFAULT_FONT_PATH, Font.PLAIN, 30);
graphics2D.setFont(font);
Color color = new Color(255, 0, 0, 255);
graphics2D.setColor(color);
graphics2D.setColor(color);
// 添加文字
String[] texts = form.getText().split("\\|");
int length = texts.length;
for (int i = 0; i < length; i++) {
graphics2D.drawString(texts[i], 30, imgHeight - (30 * (length - i) ));
}
graphics2D.dispose();
// 输出图片
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(bufImg, "JPG", outputStream);
form.setFileData(Base64.getEncoder().encodeToString(outputStream.toByteArray()));
}
/**
* description 获取自定义字体
* param [fontPath, fontStyle, fontSize]
* return java.awt.Font
* author HuangChaobin
* createTime 2020/05/28 17:49
**/
private static Font getDefaultFont(String fontPath, int fontStyle, int fontSize) throws Exception {
InputStream inputStream = WatermarkServiceImpl.class.getResourceAsStream(fontPath);
Font definedFont;
try {
definedFont = Font.createFont(Font.TRUETYPE_FONT, inputStream).deriveFont(fontStyle, fontSize);
} catch (Exception e) {
throw e;
} finally {
IOUtils.closeQuietly(inputStream);
}
return definedFont;
}
}
package com.esv.freight.file.module.file.controller;
import com.alibaba.fastjson.JSONObject;
import com.esv.freight.file.BaseTestController;
import com.esv.freight.file.common.response.ECode;
import com.esv.freight.file.module.file.form.WaterMarkForm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.junit.Assert;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Base64;
/**
* @description:
* @project: freight-file-service
* @name: com.esv.freight.file.module.file.controller.WatermarkControllerTest
* @author: 黄朝斌
* @email: huangchaobin@esvtek.com
* @createTime: 2020/05/28 14:59
* @version:1.0
*/
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class WatermarkControllerTest extends BaseTestController {
@Test
public void a1_imageWithWatermark_success_test() throws Exception {
String url = "/upload/imageWithWatermark";
// 构造数据
String filepath = "D:\\test\\1366x768_107480_8.jpg";
File file = new File(filepath);
InputStream input = new FileInputStream(file);
WaterMarkForm form = new WaterMarkForm();
form.setFileData(Base64.getEncoder().encodeToString(IOUtils.toByteArray(input)));
form.setFileName("图片水印合成.jpg");
form.setText("沈阳市和平区青年大街386号|2020/05/28 15:04");
MvcResult mvcResult = this.getMockMvc().perform(MockMvcRequestBuilders.post(url)
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
.content(form.toString()))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
String responseStr = mvcResult.getResponse().getContentAsString();
log.info(responseStr);
JSONObject result = JSONObject.parseObject(responseStr);
Assert.assertEquals(ECode.SUCCESS.code(), result.getIntValue("code"));
Assert.assertTrue(result.getJSONObject("data").containsKey("id"));
Assert.assertTrue(result.getJSONObject("data").containsKey("url"));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment