溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

詳解Java實(shí)現(xiàn)批量壓縮圖片裁剪壓縮多種尺寸縮略圖一鍵批量上傳圖片

發(fā)布時(shí)間:2020-10-15 16:27:35 來(lái)源:腳本之家 閱讀:173 作者:guobinhui 欄目:編程語(yǔ)言

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,效果如下:

詳解Java實(shí)現(xiàn)批量壓縮圖片裁剪壓縮多種尺寸縮略圖一鍵批量上傳圖片

方案二具體實(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)站的支持!

向AI問(wèn)一下細(xì)節(jié)

免責(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)容。

AI