您好,登錄后才能下訂單哦!
10萬(wàn)+IT人都在關(guān)注的圖片批量壓縮上傳方案(完整案例+代碼)
背景需求:為了客戶(hù)端訪問(wèn)圖片資源時(shí),加載圖片更流暢,體驗(yàn)更好,通常不會(huì)直接用原圖路徑,需要根據(jù)不同的場(chǎng)景顯示不同規(guī)格的縮略圖,根據(jù)商品關(guān)鍵屬性,能夠獲取到圖片不同尺寸規(guī)格的圖片路徑,并且能根據(jù)不同縮略圖直觀看到商品的關(guān)鍵屬性,需要寫(xiě)一個(gè)Java小工具把本地磁盤(pán)中的圖片資源一鍵上傳至分布式FastDFS文件服務(wù)器,并把圖片信息存入本地?cái)?shù)據(jù)庫(kù),PC端或者客戶(hù)端查詢(xún)商品時(shí),就可以根據(jù)商品的業(yè)務(wù)屬性。比如根據(jù)productId就能把商品相關(guān)的不同尺寸規(guī)格的圖片都獲取到,頁(yè)面渲染圖片資源時(shí),不同的場(chǎng)景,直接通過(guò)文件服務(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)思路:先把本地磁盤(pán)目錄中的所有圖片資源通過(guò)IO流讀出來(lái),讀到內(nèi)存中,然后對(duì)圖片的名稱(chēng)根據(jù)定義好的業(yè)務(wù)規(guī)則解析,生成不同的圖片名,然后對(duì)原圖進(jìn)行不同規(guī)格的解析壓縮處理,以及圖片資源的上傳和圖片信息的批量保存至數(shù)據(jù)庫(kù)。
常用的壓縮方案有下面2種:
方案一:對(duì)原圖進(jìn)行按照指定存儲(chǔ)空間的壓縮,比如原圖100Kb,壓縮至10Kb
方案二:對(duì)原圖進(jìn)行指定寬高大小的壓縮,比如原圖800*800,壓縮至100*100
準(zhǔn)備工作:封裝一個(gè)文件流操作的通過(guò)工具類(lèi),如下:
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)目名稱(chēng):shsc-batchUpload-server * 類(lèi)說(shuō)明:文件流工具類(lèi) * @author guobinhui * @since JDK 1.8.0_51 */ public class FileUtils { /* * 讀取本地物理磁盤(pán)目錄里的所有文件資源到程序內(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的字符串流 * 注意:通過(guò)前端頁(yè)面上傳圖片時(shí),用 MultipartFile文件流可以接收?qǐng)D片并上傳,MultipartFile流有很豐富的方法 * 本案例通過(guò)后臺(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é)輸出流寫(xiě)到指定文件 * @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è)壓縮圖片處理類(lèi)
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)目名稱(chēng):shsc-batchUpload-server * 類(lèi)說(shuō)明:圖片壓縮處理類(lèi) * @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é)輸出流寫(xiě)入文件 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)過(guò)程:
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)目名稱(chēng):shsc-batchUpload-server * 類(lèi)說(shuō)明:圖片批量壓縮上傳 * @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 "<h2 style='color:red;'>批量上傳文件成功,非常棒,壓縮上傳文件總數(shù)量為:"+num+",共計(jì)耗時(shí)"+(endWrite-startWrite)/1000+"秒</h2>"; } }
最后在瀏覽器上訪問(wèn)該接口或者把該接口放在main方法里run,效果如下:
方案二具體實(shí)現(xiàn)過(guò)程:
@RequestMapping("/upload") @ResponseBody public String upload(){ //win環(huán)境原始文件目錄 String originalFileDir = "D:/pics/pic1"; System.out.println("讀磁盤(pán)文件開(kāi)始"); long startRead = System.currentTimeMillis(); List <File> originalFileList = readFiles(originalFileDir); long endRead = System.currentTimeMillis(); System.out.println("讀磁盤(pán)文件結(jié)束"); System.out.println("讀取磁盤(pán)文件共計(jì)耗時(shí):" +(endRead-startRead)+"毫秒" ); Iterator<File> it = originalFileList.iterator(); System.out.println("壓縮拷貝文件開(kāi)始"); 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 "<h2 style='color:red;'>批量上傳文件成功,非常棒,壓縮上傳文件總數(shù)量為:"+num+",共計(jì)耗時(shí)"+(endWrite-startWrite)/1000+"秒</h2>"; } return "批量上傳文件失??!"; }
以上所述是小編給大家介紹的Java實(shí)現(xiàn)批量壓縮圖片裁剪壓縮多種尺寸縮略圖一鍵批量上傳圖片詳解整合,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)億速云網(wǎng)站的支持!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。