Java实现批量压缩图片 裁剪压缩多种尺寸缩略图 一键批量上传图片
10萬+IT人都在關注的圖片批量壓縮上傳方案(完整案例+代碼)
背景需求:為了客戶端訪問圖片資源時,加載圖片更流暢,體驗更好,通常不會直接用原圖路徑,需要根據不同的場景顯示不同規格的縮略圖,根據商品關鍵屬性,能夠獲取到圖片不同尺寸規格的圖片路徑,并且能根據不同縮略圖直觀看到商品的關鍵屬性,需要寫一個Java小工具把本地磁盤中的圖片資源一鍵上傳至分布式FastDFS文件服務器,并把圖片信息存入本地數據庫,PC端或者客戶端查詢商品時,就可以根據商品的業務屬性。比如根據productId就能把商品相關的不同尺寸規格的圖片都獲取到,頁面渲染圖片資源時,不同的場景,直接通過文件服務器的IP+存儲路徑,可以在線預覽。示例:商品id為1001的主圖原圖1001.jpg,大小為800×800(px),在本案例中解析為1001-50×50.jpg,1001-100×100.jpg,1001-200×200.jpg,1001-400×400.jpg,解析后連同原圖就是5種尺寸規格的圖片。前端就能直觀的根據屏幕大小,業務場景等因素使用不同的圖片。
實現思路:先把本地磁盤目錄中的所有圖片資源通過IO流讀出來,讀到內存中,然后對圖片的名稱根據定義好的業務規則解析,生成不同的圖片名,然后對原圖進行不同規格的解析壓縮處理,以及圖片資源的上傳和圖片信息的批量保存至數據庫。
常用的壓縮方案有下面2種:
方案一:對原圖進行按照指定存儲空間的壓縮,比如原圖100Kb,壓縮至10Kb
方案二:對原圖進行指定寬高大小的壓縮,比如原圖800*800,壓縮至100*100
準備工作:封裝一個文件流操作的通過工具類,如下:
package com.demo.utils;import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List;import org.apache.tomcat.util.codec.binary.Base64;/*** 創建時間:2019年3月13日 下午9:02:32* 項目名稱:shsc-batchUpload-server* 類說明:文件流工具類* @author guobinhui* @since JDK 1.8.0_51*/ public class FileUtils {/* * 讀取本地物理磁盤目錄里的所有文件資源到程序內存 */ public static List<File> readFiles(String fileDir) {File dirPath = new File(fileDir);//用listFiles()獲得子目錄和文件File[] files = dirPath.listFiles();List<File> list1 = new ArrayList<File>();for (int i = 0; i < files.length; i++) {File file = files[i];if (!file.isDirectory()) {list1.add(files[i]);}}System.out.println("目錄圖片數量為:"+list1.size());return list1;}/* * File文件流轉為Base64的字符串流* 注意:通過前端頁面上傳圖片時,用 MultipartFile文件流可以接收圖片并上傳,MultipartFile流有很豐富的方法* 本案例通過后臺小工具上傳,需要把圖片資源的文件流轉為Base64格式的流才可以上傳*/ public static String getBase64(File file) {FileInputStream fis = null;String base64String = null;try {fis = new FileInputStream(file);byte[] buff = new byte[fis.available()];fis.read(buff);base64String = Base64.encodeBase64String(buff);} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally{if(fis != null){try {fis.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}return base64String;}/*** 將File文件流轉為字節數組* @param file* @return*/public static byte[] getByte(File file){byte[] bytes = null;try {FileInputStream fis = new FileInputStream(file);bytes = new byte[fis.available()];fis.read(bytes);fis.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return bytes;}/*** 將字節輸出流寫到指定文件* @param os* @param file*/public static void writeFile(ByteArrayOutputStream os, File file){FileOutputStream fos = null;try {byte[] bytes = os.toByteArray();if (file.exists()) {file.delete();}fos = new FileOutputStream(file);fos.write(bytes);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {fos.close();} catch (IOException e) {e.printStackTrace();}}} }?封裝一個壓縮圖片處理類
package com.demo.mapper.entity;import java.awt.Image; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import javax.imageio.ImageIO;/*** 創建時間:2019年3月13日 下午3:35:05* 項目名稱:shsc-batchUpload-server* 類說明:圖片壓縮處理類* @author guobinhui* @since JDK 1.8.0_51*/ public class ImgCompress {private Image img; private int width; private int height;/** * 構造函數 */ public ImgCompress(String filePath) throws IOException { File file = new File(filePath);// 讀入文件 img = ImageIO.read(file); // 構造Image對象 width = img.getWidth(null); // 得到源圖寬 height = img.getHeight(null); // 得到源圖長 } public Image getImg() {return img;}public void setImg(Image img) {this.img = img;}public int getWidth() {return width;}public void setWidth(int width) {this.width = width;}public int getHeight() {return height;}public void setHeight(int height) {this.height = height;}public void reSize(int w, int h,File file,String dir) throws IOException { // SCALE_SMOOTH 的縮略算法 生成縮略圖片的平滑度的 優先級比速度高 生成的圖片質量比較好,但是速度慢 BufferedImage tag = new BufferedImage(50,50,BufferedImage.TYPE_INT_RGB );Image img = ImageIO.read(file);Image image = img.getScaledInstance(w, h, Image.SCALE_SMOOTH);tag.getGraphics().drawImage(image,50, 50, null); // 繪制縮小后的圖 // 將輸入文件轉換為字節數組byte[] bytes = FileUtils.getByte(file);// 構造輸入輸出字節流ByteArrayInputStream is = new ByteArrayInputStream(bytes);ByteArrayOutputStream os = new ByteArrayOutputStream();double rate = w/800;//縮放比率try {// 處理圖片zoomImage(is,os,rate);} catch (Exception e) {e.printStackTrace();}// 將字節輸出流寫入文件FileUtils.writeFile(os,new File(dir+"/"+file.getName()));} public void zoomImage(InputStream is, OutputStream os,double Rate) throws Exception { BufferedImage bufImg = ImageIO.read(is);AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(Rate,Rate), null);BufferedImage bufferedImage = ato.filter(bufImg, null);ImageIO.write(bufferedImage, "jpg", os);} }方案一具體實現過程:
package com.demo.controller;import java.awt.Color; import java.awt.Graphics; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List;import javax.imageio.ImageIO;import org.apache.tomcat.util.codec.binary.Base64; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import com.demo.mapper.entity.AttachmentModel; import com.demo.mapper.entity.ImgCompress; import com.demo.mapper.entity.ProductPic; import com.demo.service.IFileService; import com.demo.utils.FileUtils; import com.shsc.framework.common.ResultInfo;/*** 創建時間:2019年3月8日 下午3:03:56* 項目名稱:shsc-batchUpload-server* 類說明:圖片批量壓縮上傳* @author guobinhui* @since JDK 1.8.0_51*/ @RestController @RequestMapping(value="/file") public class FileController {@Autowired private IFileService fileServiceImpl;@RequestMapping("/test") @ResponseBody public String test() {//原始圖片目錄String originalFileDir = "D:/pics/pic1";List <File> originalFileList = readFiles(originalFileDir);Iterator<File> it = originalFileList.iterator();//壓縮后的縮略圖目錄String thumbnailDir = "D:/uploadBaseDir/productPic/20190313/thumbnail";long startWrite = System.currentTimeMillis();while(it.hasNext()){File file = (File)it.next();try {ImgCompress img = new ImgCompress(file.getPath());img.reSize(50, 50, file, thumbnailDir);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();return "上傳失敗!";} }long endWrite = System.currentTimeMillis();System.out.println("批量上傳文件共計耗時:" +(endWrite-startWrite)/1000+"秒" ); return "<h1 style='color:red;'>批量上傳文件成功,非常棒,壓縮上傳文件總數量為:"+num+",共計耗時"+(endWrite-startWrite)/1000+"秒</h1>";} }最后在瀏覽器上訪問該接口或者把該接口放在main方法里run,效果如下:
方案二具體實現過程:
@RequestMapping("/upload") @ResponseBody public String upload(){//win環境原始文件目錄String originalFileDir = "D:/pics/pic1";System.out.println("讀磁盤文件開始");long startRead = System.currentTimeMillis();List <File> originalFileList = readFiles(originalFileDir);long endRead = System.currentTimeMillis();System.out.println("讀磁盤文件結束");System.out.println("讀取磁盤文件共計耗時:" +(endRead-startRead)+"毫秒" ); Iterator<File> it = originalFileList.iterator();System.out.println("壓縮拷貝文件開始");long startWrite = System.currentTimeMillis(); // Integer size = 500;//每500個圖片批量插入一次 // Integer i = 0;String productNumber = null;String thumbnailDir = "D:/uploadBaseDir/productPic/20190313/thumbnail";String base64 = null;String new50PicName = "";String new100PicName = "";String new200PicName = "";String new400PicName = "";List <ProductPic> picList = new ArrayList<ProductPic>();int picType;List <Integer> sizeList = new ArrayList<Integer>();sizeList.add(0,50);sizeList.add(1,100);sizeList.add(2,200);sizeList.add(3,400);while(it.hasNext()){File file = (File)it.next();System.out.println("原始文件路徑為:"+file.getPath());String originalFileName= file.getName();String prefixName = originalFileName.substring(0,originalFileName.lastIndexOf("."));String ext = originalFileName.substring(originalFileName.lastIndexOf("."));byte[] buff = FileUtils.getByte(file);ByteArrayInputStream is = new ByteArrayInputStream(buff);ByteArrayOutputStream os = null;BufferedImage BI = null;base64 = getBase64(file);ResultInfo<?> r = fileServiceImpl.uploadBase64(base64,originalFileName);AttachmentModel att = (AttachmentModel)r.getData();if(originalFileName.indexOf('-') == -1) {picType = 1;productNumber = prefixName;}else {picType = 2;productNumber = originalFileName.substring(0,originalFileName.lastIndexOf("-"));}if(r.isSuccess()) {ProductPic pic = new ProductPic();BeanUtils.copyProperties(att, pic);pic.getPicName();pic.setProductId(productNumber);pic.setPicType(picType);picList.add(pic);}if(originalFileName.indexOf('-') == -1) {//不帶'-'的是商品主圖productNumber = prefixName;new50PicName = productNumber+'-'+ "50×50"+ext;new100PicName = productNumber+'-'+ "100×100"+ext;new200PicName = productNumber+'-'+ "200×200"+ext;new400PicName = productNumber+'-'+ "400×400"+ext;}else {productNumber = originalFileName.substring(0,originalFileName.lastIndexOf("-"));new50PicName = originalFileName.substring(0,originalFileName.lastIndexOf("."))+'-'+ "50×50"+ext;new100PicName = originalFileName.substring(0,originalFileName.lastIndexOf("."))+'-'+ "100×100"+ext;new200PicName = originalFileName.substring(0,originalFileName.lastIndexOf("."))+'-'+ "200×200"+ext;new400PicName = originalFileName.substring(0,originalFileName.lastIndexOf("."))+'-'+ "400×400"+ext;}try {File f = null;BI = ImageIO.read(is);for (int i = 0; i < sizeList.size(); i++) {os = new ByteArrayOutputStream();Image image = BI.getScaledInstance(sizeList.get(i),sizeList.get(i), Image.SCALE_SMOOTH);BufferedImage tag = new BufferedImage(sizeList.get(i),sizeList.get(i),BufferedImage.TYPE_INT_RGB);Graphics g = tag.getGraphics();g.setColor(Color.RED);g.drawImage(image, 0, 0, null); //繪制處理后的圖g.dispose();ImageIO.write(tag, "jpg", os);if(sizeList.get(i) == 50) {FileUtils.writeFile(os,new File(thumbnailDir+"/"+new50PicName));f = new File(thumbnailDir+"/"+new50PicName);}else if(sizeList.get(i) == 100) {FileUtils.writeFile(os,new File(thumbnailDir+"/"+new100PicName));f = new File(thumbnailDir+"/"+new100PicName);}else if(sizeList.get(i) == 200) {FileUtils.writeFile(os,new File(thumbnailDir+"/"+new200PicName));f = new File(thumbnailDir+"/"+new200PicName);}else if(sizeList.get(i) == 400) {FileUtils.writeFile(os,new File(thumbnailDir+"/"+new400PicName));f = new File(thumbnailDir+"/"+new400PicName);}base64 = getBase64(f);ResultInfo<?> rr = fileServiceImpl.uploadBase64(base64,f.getName());if(rr.isSuccess()) {AttachmentModel atta = (AttachmentModel)rr.getData();if(atta.getPicName().indexOf('-') == -1) {//不帶'-'的是商品主圖picType = 1;}else if(atta.getPicName().indexOf("-1.") != -1|| atta.getPicName().indexOf("-2.") != -1|| atta.getPicName().indexOf("-3.") != -1|| atta.getPicName().indexOf("-4.") != -1) {picType = 2;}else if((atta.getPicName().indexOf("-1-") == -1||atta.getPicName().indexOf("-2-") == -1||atta.getPicName().indexOf("-3-") == -1||atta.getPicName().indexOf("-4-") == -1)&& atta.getPicName().indexOf("-") != -1) {picType = 3;}else {picType = 4;}ProductPic pic = new ProductPic();BeanUtils.copyProperties(atta, pic);pic.getPicName();pic.setProductId(productNumber);pic.setPicType(picType);picList.add(pic);}} } catch (Exception e1) {// TODO Auto-generated catch blocke1.printStackTrace();} } int num = fileServiceImpl.insertPics(picList); if(num > 0) {long endWrite = System.currentTimeMillis();System.out.println("批量上傳文件共計耗時:" +(endWrite-startWrite)/1000+"秒" ); return "<h1 style='color:red;'>批量上傳文件成功,非常棒,壓縮上傳文件總數量為:"+num+",共計耗時"+(endWrite-startWrite)/1000+"秒</h1>"; } return "批量上傳文件失敗!"; }更多JavaEE資料請關注下面公眾號,歡迎廣大開發者朋友一起交流。筆者電話(微信):18629374628
?
總結
以上是生活随笔為你收集整理的Java实现批量压缩图片 裁剪压缩多种尺寸缩略图 一键批量上传图片的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 与合作伙伴共舞,以技术推动数字化转型
- 下一篇: java从入门到入土图_Java从入门到