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
準備工作:封裝一個文件流操作的通過工具類,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
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 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文件流轉為字節數組 * @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(); } } } } |
封裝一個壓縮圖片處理類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
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); } } |
方案一具體實現過程:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
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 block e.printstacktrace(); return "上傳失敗!" ; } } long endwrite = system.currenttimemillis(); system.out.println( "批量上傳文件共計耗時:" +(endwrite-startwrite)/ 1000 + "秒" ); return "<h1 style='color:red;'>批量上傳文件成功,非常棒,壓縮上傳文件總數量為:" +num+ ",共計耗時" +(endwrite-startwrite)/ 1000 + "秒</h1>" ; } } |
最后在瀏覽器上訪問該接口或者把該接口放在main方法里run,效果如下:
方案二具體實現過程:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
@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 block e1.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 "批量上傳文件失敗!" ; } |
以上所述是小編給大家介紹的java實現批量壓縮圖片裁剪壓縮多種尺寸縮略圖一鍵批量上傳圖片詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
原文鏈接:https://blog.csdn.net/guobinhui/article/details/88540397