詳解Java實(shí)現(xiàn)批量壓縮圖片裁剪壓縮多種尺寸縮略圖一鍵批量上傳圖片
10萬+IT人都在關(guān)注的圖片批量壓縮上傳方案(完整案例+代碼)
背景需求:為了客戶端訪問圖片資源時(shí),加載圖片更流暢,體驗(yàn)更好,通常不會(huì)直接用原圖路徑,需要根據(jù)不同的場(chǎng)景顯示不同規(guī)格的縮略圖,根據(jù)商品關(guān)鍵屬性,能夠獲取到圖片不同尺寸規(guī)格的圖片路徑,并且能根據(jù)不同縮略圖直觀看到商品的關(guān)鍵屬性,需要寫一個(gè)Java小工具把本地磁盤中的圖片資源一鍵上傳至分布式FastDFS文件服務(wù)器,并把圖片信息存入本地?cái)?shù)據(jù)庫,PC端或者客戶端查詢商品時(shí),就可以根據(jù)商品的業(yè)務(wù)屬性。比如根據(jù)productId就能把商品相關(guān)的不同尺寸規(guī)格的圖片都獲取到,頁面渲染圖片資源時(shí),不同的場(chǎng)景,直接通過文件服務(wù)器的IP+存儲(chǔ)路徑,可以在線預(yù)覽。
示例:商品id為1001的主圖原圖1001.jpg,大小為800×800(px),在本案例中解析為1001-50×50.jpg,1001-100×100.jpg,1001-200×200.jpg,1001-400×400.jpg,解析后連同原圖就是5種尺寸規(guī)格的圖片。前端就能直觀的根據(jù)屏幕大小,業(yè)務(wù)場(chǎng)景等因素使用不同的圖片。
實(shí)現(xiàn)思路:先把本地磁盤目錄中的所有圖片資源通過IO流讀出來,讀到內(nèi)存中,然后對(duì)圖片的名稱根據(jù)定義好的業(yè)務(wù)規(guī)則解析,生成不同的圖片名,然后對(duì)原圖進(jìn)行不同規(guī)格的解析壓縮處理,以及圖片資源的上傳和圖片信息的批量保存至數(shù)據(jù)庫。
常用的壓縮方案有下面2種:
方案一:對(duì)原圖進(jìn)行按照指定存儲(chǔ)空間的壓縮,比如原圖100Kb,壓縮至10Kb
方案二:對(duì)原圖進(jìn)行指定寬高大小的壓縮,比如原圖800*800,壓縮至100*100
準(zhǔn)備工作:封裝一個(gè)文件流操作的通過工具類,如下:
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; /** * 創(chuàng)建時(shí)間:2019年3月13日 下午9:02:32 * 項(xiàng)目名稱:shsc-batchUpload-server * 類說明:文件流工具類 * @author guobinhui * @since JDK 1.8.0_51 */ public class FileUtils { /* * 讀取本地物理磁盤目錄里的所有文件資源到程序內(nèi)存 */ 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("目錄圖片數(shù)量為:"+list1.size()); return list1; } /* * File文件流轉(zhuǎn)為Base64的字符串流 * 注意:通過前端頁面上傳圖片時(shí),用 MultipartFile文件流可以接收?qǐng)D片并上傳,MultipartFile流有很豐富的方法 * 本案例通過后臺(tái)小工具上傳,需要把圖片資源的文件流轉(zhuǎn)為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 block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally{ if(fis != null){ try { fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } return base64String; } /** * 將File文件流轉(zhuǎn)為字節(jié)數(shù)組 * @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; } /** * 將字節(jié)輸出流寫到指定文件 * @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(); } } } }
封裝一個(gè)壓縮圖片處理類
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; /** * 創(chuàng)建時(shí)間:2019年3月13日 下午3:35:05 * 項(xiàng)目名稱:shsc-batchUpload-server * 類說明:圖片壓縮處理類 * @author guobinhui * @since JDK 1.8.0_51 */ public class ImgCompress { private Image img; private int width; private int height; /** * 構(gòu)造函數(shù) */ public ImgCompress(String filePath) throws IOException { File file = new File(filePath);// 讀入文件 img = ImageIO.read(file); // 構(gòu)造Image對(duì)象 width = img.getWidth(null); // 得到源圖寬 height = img.getHeight(null); // 得到源圖長(zhǎng) } 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 的縮略算法 生成縮略圖片的平滑度的 優(yōu)先級(jí)比速度高 生成的圖片質(zhì)量比較好,但是速度慢 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); // 繪制縮小后的圖 // 將輸入文件轉(zhuǎn)換為字節(jié)數(shù)組 byte[] bytes = FileUtils.getByte(file); // 構(gòu)造輸入輸出字節(jié)流 ByteArrayInputStream is = new ByteArrayInputStream(bytes); ByteArrayOutputStream os = new ByteArrayOutputStream(); double rate = w/800;//縮放比率 try { // 處理圖片 zoomImage(is,os,rate); } catch (Exception e) { e.printStackTrace(); } // 將字節(jié)輸出流寫入文件 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); } }
方案一具體實(shí)現(xiàn)過程:
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; /** * 創(chuàng)建時(shí)間:2019年3月8日 下午3:03:56 * 項(xiàng)目名稱: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 block e.printStackTrace(); return "上傳失敗!"; } } long endWrite = System.currentTimeMillis(); System.out.println("批量上傳文件共計(jì)耗時(shí):" +(endWrite-startWrite)/1000+"秒" ); return "<h1 style='color:red;'>批量上傳文件成功,非常棒,壓縮上傳文件總數(shù)量為:"+num+",共計(jì)耗時(shí)"+(endWrite-startWrite)/1000+"秒</h1>"; } }
最后在瀏覽器上訪問該接口或者把該接口放在main方法里run,效果如下:
方案二具體實(shí)現(xiàn)過程:
@RequestMapping("/upload") @ResponseBody public String upload(){ //win環(huán)境原始文件目錄 String originalFileDir = "D:/pics/pic1"; System.out.println("讀磁盤文件開始"); long startRead = System.currentTimeMillis(); List <File> originalFileList = readFiles(originalFileDir); long endRead = System.currentTimeMillis(); System.out.println("讀磁盤文件結(jié)束"); System.out.println("讀取磁盤文件共計(jì)耗時(shí):" +(endRead-startRead)+"毫秒" ); Iterator<File> it = originalFileList.iterator(); System.out.println("壓縮拷貝文件開始"); long startWrite = System.currentTimeMillis(); // Integer size = 500;//每500個(gè)圖片批量插入一次 // 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 block e1.printStackTrace(); } } int num = fileServiceImpl.insertPics(picList); if(num > 0) { long endWrite = System.currentTimeMillis(); System.out.println("批量上傳文件共計(jì)耗時(shí):" +(endWrite-startWrite)/1000+"秒" ); return "<h1 style='color:red;'>批量上傳文件成功,非常棒,壓縮上傳文件總數(shù)量為:"+num+",共計(jì)耗時(shí)"+(endWrite-startWrite)/1000+"秒</h1>"; } return "批量上傳文件失?。?; }
以上所述是小編給大家介紹的Java實(shí)現(xiàn)批量壓縮圖片裁剪壓縮多種尺寸縮略圖一鍵批量上傳圖片詳解整合,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- Java 截取視頻資料中的某一幀作為縮略圖
- Java 讀取網(wǎng)絡(luò)圖片存儲(chǔ)到本地并生成縮略圖
- Java實(shí)現(xiàn)的不同圖片居中剪裁生成同一尺寸縮略圖功能示例
- java生成縮略圖的方法示例
- Java圖片裁剪和生成縮略圖的實(shí)例方法
- java實(shí)現(xiàn)創(chuàng)建縮略圖、伸縮圖片比例生成的方法
- java根據(jù)url抓取并生成縮略圖的示例
- 用java實(shí)現(xiàn)的獲取優(yōu)酷等視頻縮略圖的實(shí)現(xiàn)代碼
- Java縮略圖生成庫之Thumbnailator應(yīng)用說明
- Java實(shí)現(xiàn)自動(dòng)生成縮略圖片
相關(guān)文章
Spring Boot配置application.yml及根據(jù)application.yml選擇啟動(dòng)配置的操作
Spring Boot中可以選擇applicant.properties 作為配置文件,也可以通過在application.yml中進(jìn)行配置,讓Spring Boot根據(jù)你的選擇進(jìn)行加載啟動(dòng)配置文件,本文給大家介紹Spring Boot配置application.yml及根據(jù)application.yml選擇啟動(dòng)配置的操作方法,感興趣的朋友一起看看吧2023-10-10idea集成shell運(yùn)行環(huán)境以及shell輸出中文亂碼的解決
這篇文章主要介紹了idea集成shell運(yùn)行環(huán)境以及shell輸出中文亂碼的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08SpringCloud微服務(wù)之Hystrix組件實(shí)現(xiàn)服務(wù)熔斷的方法
微服務(wù)架構(gòu)特點(diǎn)就是多服務(wù),多數(shù)據(jù)源,支撐系統(tǒng)應(yīng)用。這樣導(dǎo)致微服務(wù)之間存在依賴關(guān)系。這篇文章主要介紹了SpringCloud微服務(wù)之Hystrix組件實(shí)現(xiàn)服務(wù)熔斷的方法,需要的朋友可以參考下2019-08-08Spring中的攔截器HandlerInterceptor詳細(xì)解析
這篇文章主要介紹了Spring中的攔截器HandlerInterceptor詳細(xì)解析,HandlerInterceptor 是 Spring 框架提供的一個(gè)攔截器接口,用于在請(qǐng)求處理過程中攔截和處理請(qǐng)求,需要的朋友可以參考下2024-01-01