最近的未成年人保護在互聯網也是一浪高過一浪,爲了支持政府的政策,對未成年人保護。我們的商城也做了個實名認證的功能。這個功能能夠根據用戶上傳的身份證信息自動判定是否爲未成年,進而做出相應的業務處理。
問題點1:在於我們使用的三方服務ocr接口限制文件傳輸爲1M,也就是說你的圖片過大,就會出現識別報錯的問題。而現在的高像素手機,隨便一拍就是幾兆,必然要做圖片壓縮的處理。
問題點2:用戶用的不同的手機,拍出來的照片,或者傳輸的照片的圖片格式也是各式各樣。但是三方服務接口就接受三種類型的圖片。jpg,bmp,jpeg。沒有辦法。要麼就是對別的類型在接口層控制住,提示用戶格式不正確。要麼處理圖片的格式。
以上這就是本篇的業務場景,和要解決的問題點。
下面對上面的兩個問題來做處理。 接口接受前端上傳的照片:
代碼分爲三步:
- 首先接收到圖片文件後進行壓縮,轉換圖片類型。也是本節要解決的問題!
- 對圖片進行Base64轉碼。這個是三方服務的接口要求。
- 調用業務層進行後續操作。
1.首先是引入依賴:
<!--圖片壓縮工具類thumbnailator-->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
2.然後就是代碼部分。工具類
2.1 controller層的私有公共方法
/**
* [圖片轉換格式,壓縮公共方法]
*
* @param multipartFile
* @return
* @throws IOException
*/
private MultipartFile getCompressFile(MultipartFile multipartFile) throws IOException {
List fileTypeList = new ArrayList();
fileTypeList.add(FILE_TYPE_IMAGE_EXT_JPG.getId());
fileTypeList.add(FILE_TYPE_IMAGE_EXT_BMP.getId());
fileTypeList.add(FILE_TYPE_IMAGE_EXT_JPEG.getId());
String filePath = FileUtil.getFileAbsolutePath("doc", "jpg");
LOGGER.info("緩存文件的絕對路徑:" + filePath);
//圖片壓縮
return ImageUtil.compressFile(multipartFile, filePath, fileTypeList);
}
2.2 獲取臨時文件在服務器上的絕對路徑的方法
import java.io.File;
import java.util.UUID;
/**
* 文件操作工具類
* @date 2019-11-09
* @author zhanglifeng
*/
public class FileUtil {
public static String getFileAbsolutePath(String filePath,String fileType){
StringBuilder sb =new StringBuilder();
String fileName = sb.append(UUID.randomUUID()).append(".").append(fileType).toString();
sb.setLength(0);
sb.append(FileUtil.class.getClassLoader().getResource("").getPath());
sb.append(filePath).append(File.separator).append(fileName);
String path = sb.toString().replaceAll("\\\\", "\\/");
return path;
}
}
2.3 壓縮,轉換圖片類型的工具類
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
/**
* 獲取圖片尺寸和截圖 工具類
*
* @author zhanglifeng
* @date 2019-11-08
*/
public class ImageUtil {
private final static Logger logger = LoggerFactory.getLogger(ImageUtil.class);
/**
* [壓縮要上傳的文件,並將文件類型轉爲指定的文件類型集合中的一個。]
*
* @param file 要上傳的文件
* @param absolutePath 臨時文件的絕對路徑
* @param fileTypeList 文件轉成的類型集合
* @return
*/
public static MultipartFile compressFile(MultipartFile file, String absolutePath, List<String> fileTypeList) throws IOException {
//記錄原MultipartFile,如果壓縮異常就用原來的MultipartFile
MultipartFile oldMultipartFile = file;
FileInputStream fileInputStream = null;
try {
String fileName = file.getName();
String originalFilename = file.getOriginalFilename();
String contentType = file.getContentType();
//獲取要上傳的文件後綴
String fileExt = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
File tempFile = new File(absolutePath);
if (fileTypeList.contains(fileExt)) {
//如果文件類型符合,則只壓縮就好了
Thumbnails.of(file.getInputStream())
.scale(1f)
.outputQuality(0.2f)
.toFile(tempFile);
} else {
//如果文件類型不在指定的集合內。則要轉格式,並壓縮
Thumbnails.of(file.getInputStream())
.scale(1f)
.outputFormat(fileTypeList.get(0))
.outputQuality(0.2f)
.toFile(tempFile);
originalFilename = originalFilename.replace("." + fileExt, "." + fileTypeList.get(0));
}
fileInputStream = new FileInputStream(tempFile);
file = new MockMultipartFile(fileName, originalFilename, contentType, fileInputStream);
boolean success = tempFile.delete();
logger.info("刪除臨時file success:{}", success);
} catch (IOException e) {
logger.error("壓縮圖片失敗,把MultipartFile賦值爲原來的值oldFile,exception:{}", e);
file = oldMultipartFile;
} finally {
fileInputStream.close();
}
return file;
}
}
然後可以本地通過postman調用測試接口,可以先註釋掉刪除臨時文件的代碼。可以看到壓縮後的文件才幾十到幾百kb.
並且png格式的圖片變成jpg格式的。目標達成!
如果感覺圖片壓縮的太過或者還要在壓縮。可以調整這個值:outputQuality(0.2f)
的大小。甚至可以一遍不行來兩邊。