您好,登錄后才能下訂單哦!
這篇文章主要講解了“如何使用ServletInputStream()輸入流讀取圖片方式”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“如何使用ServletInputStream()輸入流讀取圖片方式”吧!
問(wèn)題描述
項(xiàng)目結(jié)構(gòu)
問(wèn)題原因
解決方法
總結(jié)回顧
最近遇到需要用到上傳圖片到服務(wù)器上,學(xué)習(xí)了一下原生servlet中的form上傳圖片保存到指定目錄的情況
思路:前端提交–servlet獲取inputstream–輸出到本地
獲取輸入流后輸出到本地一直打不開(kāi)提示損壞/0kb.從網(wǎng)上看到有說(shuō)需要apache的兩個(gè)包io和fileupload包.我想的是不借助第三方工具包處理(tomcat也是第三方呵呵,純的應(yīng)該是利用socket吧)
如圖所示:并未使用其余組件,創(chuàng)建了一個(gè)動(dòng)態(tài)java項(xiàng)目即可
網(wǎng)上查到一片文章,大概意思是,上傳文件不是單純的文件流,其與本地io不同其中多了些東西.按照本地上傳下載的方式無(wú)法解析出來(lái).包括些分隔符\和表單的一些信息,需要重新處理
手動(dòng)解析出圖片的流,并把其中的多余東西去掉,然后將得到的純文件流輸出到指定位置
該問(wèn)題居然查不到當(dāng)前時(shí)間的帖子,一般都是2-3年前的讓我有點(diǎn)意外.知其然而不知其所以然早晚被人家掣肘.在框架琳瑯滿目的當(dāng)下抄抄寫(xiě)寫(xiě)確實(shí)能解決問(wèn)題而且真的是事半功倍.
另寫(xiě)代碼要多查多看api文檔
多動(dòng)手敲代碼,不然不知道所以然,這么點(diǎn)破問(wèn)題弄了個(gè)周末
package server; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringReader; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @SuppressWarnings("serial") @WebServlet(name = "streams",urlPatterns = "/UploadServlet.do") public class CsvTest extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); final int NONE = 0; // 狀態(tài)碼,表示沒(méi)有特殊操作 final int DATAHEADER = 1; // 表示下一行要讀到報(bào)頭信息 final int FILEDATA = 2; // 表示下面要讀的是上傳文件和二進(jìn)制數(shù)據(jù) final int FIELDDATA = 3; // 表示下面要讀到表單域的文本值 // 請(qǐng)求消息實(shí)體的總長(zhǎng)度(請(qǐng)求消息中除消息頭之外的數(shù)據(jù)長(zhǎng)度) int totalbytes = request.getContentLength(); File f; // 上傳文件儲(chǔ)存在服務(wù)器上 // 容納請(qǐng)求消息實(shí)體的字節(jié)數(shù)組 byte[] dataOrigin = new byte[totalbytes]; // 對(duì)于post多個(gè)文件的表單,b作為原始數(shù)據(jù)的副本提供提取文件數(shù)據(jù)的操作 byte[] b = new byte[totalbytes]; // 請(qǐng)求消息類型 String contentType = request.getContentType(); String fieldname = ""; // 表單域的名稱 String fieldvalue = ""; // 表單域的值 String fileFormName = ""; // 上傳的文件再表單中的名稱 String fileRealName = ""; // 上傳文件的真實(shí)名字 String boundary = ""; // 分界符字符串 String lastboundary = ""; // 結(jié)束分界符字符串 int fileSize = 0; // 文件長(zhǎng)度 // 容納表單域的名稱/值的哈希表 Map<String, String> formfieldsTable = new HashMap<String, String>(); // 容納文件域的名稱/文件名的哈希表 Map<String, String> filenameTable = new HashMap<String, String>(); // 在消息頭類型中找到分界符的定義 int pos = contentType.indexOf("boundary="); int pos2; // position2 if (pos != -1) { pos += "boundary=".length(); boundary = "--" + contentType.substring(pos); // 解析出分界符 lastboundary = boundary + "--"; // 得到結(jié)束分界符 } int state = NONE; // 起始狀態(tài)為NONE // 得到請(qǐng)求消息的數(shù)據(jù)輸入流 DataInputStream in = new DataInputStream(request.getInputStream()); in.readFully(dataOrigin); // 根據(jù)長(zhǎng)度,將消息實(shí)體的內(nèi)容讀入字節(jié)數(shù)組dataOrigin中 in.close(); // 關(guān)閉數(shù)據(jù)流 String reqcontent = new String(dataOrigin); // 從字節(jié)數(shù)組中得到表示實(shí)體的字符串 // 從字符串中得到輸出緩沖流 BufferedReader reqbuf = new BufferedReader(new StringReader(reqcontent)); // 設(shè)置循環(huán)標(biāo)志 boolean flag = true; // int i = 0; while (flag == true) { String s = reqbuf.readLine(); if (s == lastboundary || s == null) break; switch (state) { case NONE: if (s.startsWith(boundary)) { // 如果讀到分界符,則表示下一行一個(gè)頭信息 state = DATAHEADER; // i += 1; } break; case DATAHEADER: pos = s.indexOf("filename="); // 先判斷出這是一個(gè)文本表單域的頭信息,還是一個(gè)上傳文件的頭信息 if (pos == -1) { // 如果是文本表單域的頭信息,解析出表單域的名稱 pos = s.indexOf("name="); pos += "name=".length() + 1; // 1表示后面的"的占位 s = s.substring(pos); int l = s.length(); s = s.substring(0, l - 1); // 應(yīng)該是" fieldname = s; // 表單域的名稱放入fieldname out.print("fieldname=" + fieldname); state = FIELDDATA; // 設(shè)置狀態(tài)碼,準(zhǔn)備讀取表單域的值 } else { // 如果是文件數(shù)據(jù)的頭,先存儲(chǔ)這一行,用于在字節(jié)數(shù)組中定位 String temp = s; // 先解析出文件名 pos = s.indexOf("name="); pos += "name=".length() + 1; // 1表示后面的"的占位 pos2 = s.indexOf("filename="); String s1 = s.substring(pos, pos2 - 3); // 3表示";加上一個(gè)空格 fileFormName = s1; pos2 += "filename=".length() + 1; // 1表示后面的"的占位 s = s.substring(pos2); int l = s.length(); s = s.substring(0, l - 1); pos2 = s.lastIndexOf("\\"); // 對(duì)于IE瀏覽器的設(shè)置 s = s.substring(pos2 + 1); fileRealName = s; out.print("fileRealName=" + fileRealName + "<br>"); out.print("fileRealName.length()=" + fileRealName.length() + "<br>"); if (fileRealName.length() != 0) { // 確定有文件被上傳 // 下面這一部分從字節(jié)數(shù)組中取出文件的數(shù)據(jù) b = dataOrigin; // 復(fù)制原始數(shù)據(jù)以便提取文件 pos = byteIndexOf(b, temp, 0); // 定位行 // 定位下一行,2 表示一個(gè)回車和一個(gè)換行占兩個(gè)字節(jié) b = subBytes(b, pos + temp.getBytes().length + 2, b.length); // 再讀一行信息,是這一部分?jǐn)?shù)據(jù)的Content-type s = reqbuf.readLine(); // 設(shè)置文件輸入流,準(zhǔn)備寫(xiě)文件 f = new File("C:" + File.separator +"Users" + File.separator +"Administrator" + File.separator +"Desktop" + File.separator +fileRealName); DataOutputStream fileout = new DataOutputStream( new FileOutputStream(f)); // 字節(jié)數(shù)組再往下一行,4表示兩回車換行占4個(gè)字節(jié),本行的回車換行2個(gè)字節(jié),Content-type的下 // 一行是回車換行表示的空行,占2個(gè)字節(jié) // 得到文件數(shù)據(jù)的起始位置 b = subBytes(b, s.getBytes().length + 4, b.length); pos = byteIndexOf(b, boundary, 0); // 定位文件數(shù)據(jù)的結(jié)尾 b = subBytes(b, 0, pos - 1); // 取得文件數(shù)據(jù) fileout.write(b, 0, b.length - 1); // 將文件數(shù)據(jù)存盤(pán) fileout.close(); fileSize = b.length - 1; // 文件長(zhǎng)度存入fileSize out.print("fileFormName=" + fileFormName + " filename=" + fileRealName + " fileSize=" + fileSize + "<br>"); filenameTable.put(fileFormName, fileRealName); state = FILEDATA; } } break; case FIELDDATA: // 讀取表單域的值 s = reqbuf.readLine(); fieldvalue = s; // 存入fieldvalue out.print(" fieldvalue=" + fieldvalue + "<br>"); formfieldsTable.put(fieldname, fieldvalue); state = NONE; break; case FILEDATA: // 如果是文件數(shù)據(jù)不進(jìn)行分析,直接讀過(guò)去 while ((!s.startsWith(boundary)) && (!s.startsWith(lastboundary))) { s = reqbuf.readLine(); if (s.startsWith(boundary)) { state = DATAHEADER; } else { break; } } break; } } // 指定內(nèi)容類型,并且可以顯示中文 out.println("<HTML"); out.println("<HEAD><TITLE>文件上傳結(jié)果</TITLE></HEAD>"); out.println("<BODY>"); out.println("<H1>文件上傳結(jié)果</H1><hr>"); out.println("ID為" + formfieldsTable.get("FileID1") + "的文件" + filenameTable.get("FileData1") + "已經(jīng)上傳!<br>"); out.println("ID為" + formfieldsTable.get("FileID2") + "的文件" + filenameTable.get("FileData2") + "已經(jīng)上傳!<br>"); // out.println("i = " + i + "<br>"); out.println("</BODY>"); out.println("</HTML>"); } private static int byteIndexOf(byte[] b, String s, int start) { return byteIndexOf(b, s.getBytes(), start); } private static int byteIndexOf(byte[] b, byte[] s, int start) { int i; if (s.length == 0) { return 0; } int max = b.length - s.length; if (max < 0) { return -1; } if (start > max) { return -1; } if (start < 0) { start = 0; } // 在b中找到s的第一個(gè)元素 search: for (i = start; i <= max; i++) { if (b[i] == s[0]) { // 找到了s中的第一個(gè)元素后,比較剩余的部分是否相等 int k = 1; while (k < s.length) { if (b[k + i] != s[k]) { continue search; } k++; } return i; } } return -1; } private static byte[] subBytes(byte[] b, int from, int end) { byte[] result = new byte[end - from]; System.arraycopy(b, from, result, 0, end - from); return result; } private static String subBytesString(byte[] b, int from, int end) { return new String(subBytes(b, from, end)); } }
感謝各位的閱讀,以上就是“如何使用ServletInputStream()輸入流讀取圖片方式”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)如何使用ServletInputStream()輸入流讀取圖片方式這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(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)容。