最近遇到一個問題,要求是在把一張存在于網絡上的圖片進行下載和壓縮。
解決思路:
1、獲取圖片的輸入流
2、得到圖片的字節流
3、使用google的thumbnailator.jar對字節流進行壓縮
4、把壓縮后的字節流重新轉換為輸入流
5、設置下載地址,下載到本地或ftp服務器
實現
這里只介紹下載到本地的具體實現方式
我才用的是Spring boot + maven搭建的測試項目
首先要引入google的thumbnailator的引用
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
構建圖片壓縮轉換的工具類
import net.coobird.thumbnailator.Thumbnails;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
/**
* 文件處理工具類
*
*/
public class UploadUtils {
/**
* 從輸入流中獲取數據
* @param inStream
* @return
* @throws Exception
*/
public static byte[] readInputStream(InputStream inStream) throws Exception {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, len);
}
inStream.close();
return outStream.toByteArray();
}
/**
* 根據指定大小壓縮圖片
*
* @param imageBytes 源圖片字節數組
* @param desFileSize 指定圖片大小,單位kb
* @return 壓縮質量后的圖片字節數組
*/
public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize) {
if (imageBytes == null || imageBytes.length <= 0 || imageBytes.length < desFileSize * 1024) {
return imageBytes;
}
long srcSize = imageBytes.length;
double accuracy = getAccuracy(srcSize / 1024);
try {
while (imageBytes.length > desFileSize * 1024) {
ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
Thumbnails.of(inputStream)
.scale(accuracy)
.outputQuality(accuracy)
.toOutputStream(outputStream);
imageBytes = outputStream.toByteArray();
}
System.out.println("【圖片壓縮】| 圖片原大小={" + srcSize / 1024 + "}kb | 壓縮后大小={" + imageBytes.length / 1024 + "}kb | ");
} catch (Exception e) {
System.out.println("【圖片壓縮】msg=圖片壓縮失敗!" + e);
}
return imageBytes;
}
/**
* 自動調節精度(經驗數值)
*
* @param size 源圖片大小
* @return 圖片壓縮質量比
*/
private static double getAccuracy(long size) {
double accuracy;
if (size < 900) {
accuracy = 0.85;
} else if (size < 2047) {
accuracy = 0.6;
} else if (size < 3275) {
accuracy = 0.44;
} else {
accuracy = 0.4;
}
return accuracy;
}
}
編寫測試方法
public static void main(String[] args) throws Exception {
//這里同樣用File獲取一下文件,便于拿到文件的名稱、類型等信息
File file = new File(imageUrl);
//http://xxx/xxx/xxx.png(jpg等等)
URL url = new URL("完整圖片地址");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
//通過輸入流獲取圖片數據
InputStream urlInputStream = conn.getInputStream();
//獲取圖片的字節流
byte[] imgBytes = readInputStream(urlInputStream);
//壓縮圖片
byte[] minImgBytes = compressPicForScale(imgBytes, 40);
//將壓縮后的字節流轉換為輸入流
InputStream inputStream = new ByteArrayInputStream(minImgBytes);
//獲取圖片字節流并寫入磁盤
outputStreamFile(readInputStream(inputStream), "20190426095107749847010.png");
//上傳文件到ftp(FTPUtils:自定義ftp工具類)
//String uploadFilePath = FTPUtils.uploadFile("20190426095107749847010.png", filePath, inputStream);
}