如何實(shí)現(xiàn)java webApp異步上傳圖片,先了解以下幾個(gè)問題:
1.圖片上傳;
2.圖片上傳預(yù)覽;
3.上傳圖片更改地址異步添加到數(shù)據(jù)庫(kù);
主要內(nèi)容
本示例主要采用純HTML前端和JavaScript代碼作工具,查詢有關(guān)demo其實(shí)現(xiàn)圖片上傳的代碼范例如下:
(1)點(diǎn)擊上傳圖片的div代碼:
1
2
3
4
5
6
|
< div id = "div1" class = "photo" > < input type = "file" id = "choose" accept = "image/*" multiple > < a id = "upload" >上傳圖片</ a > < a class = "myinputimg" onclick = "selectphoto();" >從圖庫(kù)中選擇</ a > < a class = "myinputimg" id = "back" >取消</ a > </ div > |
(2)javaScript代碼
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
|
<script type= "text/javascript" > //獲取上傳圖片的input表單元素 var filechooser = document.getElementById( "choose" ); //創(chuàng)建用于壓縮圖片的canvas var canvas = document.createElement( "canvas" ); //獲取canvas的視覺屬性 var ctx = canvas.getContext( '2d' ); //瓦片canva var tCanvas = document.createElement( "canvas" ); var tctx = tCanvas.getContext( "2d" ); //畫布的大小 var maxsize = 100 * 1024; //上傳圖片點(diǎn)擊事件 $( "#upload" ).on( "click" , function () { filechooser.click(); }) .on( "touchstart" , function () { //添加元素屬性 $( this ).addClass( "touch" ); }) .on( "touchend" , function () { //移除元素屬性 $( this ).removeClass( "touch" ); }); //元素改變 filechooser.onchange = function () { //如果選擇為空,返回操作 if (! this .files.length) return ; //創(chuàng)建上傳圖片的數(shù)組 var files = Array.prototype.slice.call( this .files); //選擇為數(shù)量大于1張時(shí),反回操作,這里根據(jù)需求設(shè)定;pc端測(cè)試一次可以上傳若干張圖片,移動(dòng)端選擇一張,頁(yè)面只能預(yù)覽一張。由于是移動(dòng)端,所以作此判斷。 if (files.length >1) { alert( "一次只能上傳1張圖片" ); return ; } //遍歷上傳圖片的文件數(shù)組,可不用遍歷,直接取即可。 files.forEach( function (file, i) { //判斷圖片格式 if (!/\/(?:jpeg|png|gif)/i.test(file.type)) return ; var reader = new FileReader(); var li = document.createElement( "li" ); // 獲取圖片大小 var size = file.size / 1024 > 1024 ? (~~(10 * file.size / 1024 / 1024)) / 10 + "MB" : ~~(file.size / 1024) + "KB" ; //圖片預(yù)覽 li.innerHTML = '<div class="progress"><span></span></div><div class="size">' + size + '</div>' ; //追加圖片預(yù)覽代碼; $( ".img-list" ).append($(li)); reader.onload = function () { var result = this .result; var img = new Image(); img.src = result; //圖片顯示 $(li).css( "background-image" , "url(" + result + ")" ); //如果圖片大小小于100kb,則直接上傳 if (result.length <= maxsize) { img = null ; upload(result, file.type, $(li)); return ; } // 圖片加載完畢之后進(jìn)行壓縮,然后上傳 if (img.complete) { callback(); } else { img.onload = callback; } function callback() { var data = compress(img); upload(data, file.type, $(li)); img = null ; } }; reader.readAsDataURL(file); }); }; //以下是圖片壓縮相關(guān); //使用canvas對(duì)大圖片進(jìn)行壓縮 function compress(img) { var initSize = img.src.length; var width = img.width; var height = img.height; //如果圖片大于四百萬像素,計(jì)算壓縮比并將大小壓至400萬以下 var ratio; if ((ratio = width * height / 4000000) > 1) { ratio = Math.sqrt(ratio); width /= ratio; height /= ratio; } else { ratio = 1; } canvas.width = width; canvas.height = height; //鋪底色 ctx.fillStyle = "#fff" ; ctx.fillRect(0, 0, canvas.width, canvas.height); //如果圖片像素大于100萬則使用瓦片繪制 var count; if ((count = width * height / 1000000) > 1) { count = ~~(Math.sqrt(count) + 1); //計(jì)算要分成多少塊瓦片 // 計(jì)算每塊瓦片的寬和高 var nw = ~~(width / count); var nh = ~~(height / count); tCanvas.width = nw; tCanvas.height = nh; for ( var i = 0; i < count; i++) { for ( var j = 0; j < count; j++) { tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh); ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh); } } } else { ctx.drawImage(img, 0, 0, width, height); } //進(jìn)行最小壓縮 var ndata = canvas.toDataURL( 'image/jpeg' , 0.1); console.log( '壓縮前:' + initSize); console.log( '壓縮后:' + ndata.length); console.log( '壓縮率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%" ); tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0; return ndata; } //圖片上傳,將base64的圖片轉(zhuǎn)成二進(jìn)制對(duì)象,塞進(jìn)formdata上傳 function upload(basestr, type, $li) { var text = window.atob(basestr.split( "," )[1]); var buffer = new Uint8Array(text.length); var pecent = 0, loop = null ; for ( var i = 0; i < text.length; i++) { buffer[i] = text.charCodeAt(i); } var blob = getBlob([buffer], type); var xhr = new XMLHttpRequest(); var formdata = getFormData(); formdata.append( 'upload' , blob); //異步請(qǐng)求kindeditor插件的上傳圖片jsp頁(yè)面 xhr.open( 'post' , '<%=request.getContextPath()%>/kindeditor/jsp/upload_json.jsp' ); xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { //返回服務(wù)器端的圖片地址 var face_img=xhr.responseText; var id=$( "#arId" ).text(); //異步像數(shù)據(jù)庫(kù)中添加圖片 $.ajax({ type: "POST" , //異步請(qǐng)求Struts的action類將圖片地址插入數(shù)據(jù)庫(kù) url: "add_article_faceurl.action" , dataType: "json" , data: "faceurl=" +face_img+ "&id=" +id, async: true , success: function (msg){ //取添加數(shù)據(jù)庫(kù)中的圖片相關(guān)的id值,存入頁(yè)面隱藏區(qū)域 $( "#arId" ).text(msg); }, error: function (a){} }); } }; //模擬上傳進(jìn)度顯示 //數(shù)據(jù)發(fā)送進(jìn)度,前50%展示該進(jìn)度 xhr.upload.addEventListener( 'progress' , function (e) { if (loop) return ; pecent = ~~(100 * e.loaded / e.total) / 2; $li.find( ".progress span" ).css( 'width' , pecent + "%" ); if (pecent == 50) { mockProgress(); } }, false ); //數(shù)據(jù)后50%用模擬進(jìn)度 function mockProgress() { if (loop) return ; loop = setInterval( function () { pecent++; $li.find( ".progress span" ).css( 'width' , pecent + "%" ); if (pecent == 99) { clearInterval(loop); } }, 100); } xhr.send(formdata); } /** * 獲取blob對(duì)象的兼容性寫法 * @param buffer * @param format * @returns {*} */ function getBlob(buffer, format) { try { return new Blob(buffer, {type: format}); } catch (e) { var bb = new (window.BlobBuilder || window.WebKitBlobBuilder || window.MSBlobBuilder); buffer.forEach( function (buf) { bb.append(buf); }); return bb.getBlob(format); } } /** * 獲取formdata */ function getFormData() { var isNeedShim = ~navigator.userAgent.indexOf( 'Android' ) && ~navigator.vendor.indexOf( 'Google' ) && !~navigator.userAgent.indexOf( 'Chrome' ) && navigator.userAgent.match(/AppleWebKit\/(\d+)/).pop() <= 534; return isNeedShim ? new FormDataShim() : new FormData(); } /** * formdata 補(bǔ)丁, 給不支持formdata上傳blob的android機(jī)打補(bǔ)丁 * @constructor */ function FormDataShim() { console.warn( 'using formdata shim' ); var o = this , parts = [], boundary = Array(21).join( '-' ) + (+ new Date() * (1e16 * Math.random())).toString(36), oldSend = XMLHttpRequest.prototype.send; this .append = function (name, value, filename) { parts.push( '--' + boundary + '\r\nContent-Disposition: form-data; name="' + name + '"' ); if (value instanceof Blob) { parts.push( '; filename="' + (filename || 'blob' ) + '"\r\nContent-Type: ' + value.type + '\r\n\r\n' ); parts.push(value); } else { parts.push( '\r\n\r\n' + value); } parts.push( '\r\n' ); }; // Override XHR send() XMLHttpRequest.prototype.send = function (val) { var fr, data, oXHR = this ; if (val === o) { // Append the final boundary string parts.push( '--' + boundary + '--\r\n' ); // Create the blob data = getBlob(parts); // Set up and read the blob into an array to be sent fr = new FileReader(); fr.onload = function () { oldSend.call(oXHR, fr.result); }; fr.onerror = function (err) { throw err; }; fr.readAsArrayBuffer(data); // Set the multipart content type and boudary this .setRequestHeader( 'Content-Type' , 'multipart/form-data; boundary=' + boundary); XMLHttpRequest.prototype.send = oldSend; } else { oldSend.call( this , val); } }; } </script> |
(3)kindeditor插件的上傳圖片jsp頁(yè)面相關(guān)代碼.
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
|
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="java.util.*,java.io.*" %> <%@ page import="java.text.SimpleDateFormat" %> <%@ page import="org.apache.commons.fileupload.*" %> <%@ page import="org.apache.commons.fileupload.disk.*" %> <%@ page import="org.apache.commons.fileupload.servlet.*" %> <%@ page import="org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper"%> <%@ page import="org.json.simple.*" %> <% /** * KindEditor JSP * * 本JSP程序是演示程序,建議不要直接在實(shí)際項(xiàng)目中使用。 * 如果您確定直接使用本程序,使用之前請(qǐng)仔細(xì)確認(rèn)相關(guān)安全設(shè)置。 * */ //文件保存目錄路徑 String savePath = pageContext.getServletContext().getRealPath("/") + "attached/"; //String savePath = "http:\\\\192.168.1.226:8080\\qslnbase\\uploadFile/"; //String savePath = "D:/WWW/qslnADP/ADP/WebRoot/kindeditor/attached/"; //文件保存目錄URL String saveUrl = request.getContextPath() + "/attached/"; //定義允許上傳的文件擴(kuò)展名 HashMap< String , String> extMap = new HashMap< String , String>(); extMap.put("image", "gif,jpg,jpeg,png,bmp,blob"); extMap.put("flash", "swf,flv"); extMap.put("media", "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb"); extMap.put("file", "doc,docx,xls,xlsx,ppt,htm,html,txt,zip,rar,gz,bz2"); //最大文件大小 long maxSize = 1000000; response.setContentType("text/html; charset=UTF-8"); if(!ServletFileUpload.isMultipartContent(request)){ out.println(getError("請(qǐng)選擇文件。")); return; } //檢查目錄 File uploadDir = new File(savePath); if(!uploadDir.isDirectory()){ out.println(getError("上傳目錄不存在。")); return; } //檢查目錄寫權(quán)限 if(!uploadDir.canWrite()){ out.println(getError("上傳目錄沒有寫權(quán)限。")); return; } String dirName = request.getParameter("dir"); if (dirName == null) { dirName = "image"; } if(!extMap.containsKey(dirName)){ out.println(getError("目錄名不正確。")); return; } //創(chuàng)建文件夾 savePath += dirName + "/"; saveUrl += dirName + "/"; File saveDirFile = new File(savePath); if (!saveDirFile.exists()) { saveDirFile.mkdirs(); } SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); String ymd = sdf.format(new Date()); savePath += ymd + "/"; saveUrl += ymd + "/"; File dirFile = new File(savePath); if (!dirFile.exists()) { dirFile.mkdirs(); } //Struts2 請(qǐng)求 包裝過濾器 MultiPartRequestWrapper wrapper = (MultiPartRequestWrapper) request; //獲得上傳 的文件名 String fileName1 = wrapper.getFileNames("upload")[0]; //獲得文件過濾器 File file = wrapper.getFiles("upload")[0]; //檢查文件大小 if(file.length() > maxSize){ out.println(getError("上傳文件大小超過限制。")); return; } //檢查擴(kuò)展名 String fileExt1 = fileName1.substring(fileName1.lastIndexOf(".") + 1).toLowerCase(); //重構(gòu)上傳文件名 SimpleDateFormat df1 = new SimpleDateFormat("yyyyMMddHHmmss"); String newFileName1 = df1.format(new Date()) + "_" + new Random().nextInt(1000) + "." + fileExt1; byte[] buffer = new byte[1024]; //獲取文件輸出流 FileOutputStream fos = new FileOutputStream(savePath + newFileName1); String url=savePath + newFileName1; out.println(url); //獲取內(nèi)存中當(dāng)前文件輸入流 InputStream in = new FileInputStream(file); try { int num = 0; while ((num = in.read(buffer)) > 0) { fos.write(buffer, 0, num); } } catch (Exception e) { e.printStackTrace(System.err); } finally { in.close(); fos.close(); } %> <%! private String getError(String message) { JSONObject obj = new JSONObject(); obj.put("error", 1); obj.put("message", message); return obj.toJSONString(); } %> |
(4)有關(guān)kindeditor上傳圖片的jar包有如下所示
A.commons-fileupload-1.2.1.jar
B.commons-io-1.4.jar
C.json_simple-1.1.jar
這里沒有用到有關(guān)于kindeditor的js代碼,具體可參考:Kindeditor實(shí)現(xiàn)圖片自動(dòng)上傳功能
(5)有關(guān)kindeditor上傳圖片預(yù)覽的div如下
1
2
3
4
5
6
7
|
< div id = "div2" > < ul class = "img-list" > < li id = "wy" > < img style = "height:100%;width:100%;position:absolute;top:0px;" src="<%=request.getContextPath()%>/shequ/images/index.png;" > </ li > </ ul > </ div > |
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。