使用Servlet從微信小程式請求的檔案流獲取檔案內容和表單資料
阿新 • • 發佈:2019-02-19
說明:專案中用到微信小程式上傳檔案,發現檔案放在流中,Struts中request經過封裝無法獲取到此檔案流,嘗試用servlet解決
package com.web; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; public class UploadServlet extends HttpServlet { private int code = 1; private String msg = "操作成功"; private String errMsg = "操作異常"; /** * */ private static final long serialVersionUID = -6604724772593287543L; /** * Constructor of the object. */ public UploadServlet() { super(); } /** * Destruction of the servlet. <br> */ public void destroy() { super.destroy(); // Just puts "destroy" string in log } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } /** * The doPost method of the servlet. <br> */ @SuppressWarnings("deprecation") public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 這兩行語句要在獲取輸出流之前執行,才會生效 response.setCharacterEncoding("UTF-8"); response.setContentType("application/json"); //判斷enctype:判斷提交上來的資料是否是上傳表單的資料 if(!ServletFileUpload.isMultipartContent(request)){ code = -1; msg = "不是上傳檔案"; this.outPut(response,null); //按照傳統方式獲取資料 return; } request.setCharacterEncoding("utf-8"); //設定編碼 //獲得磁碟檔案條目工廠 DiskFileItemFactory factory = new DiskFileItemFactory(); //如果沒以下兩行設定的話,上傳大的檔案會佔用很多記憶體, //設定暫時存放的儲存室,這個儲存室可以和最終儲存檔案的目錄不同 /** * 原理: 它是先存到暫時儲存室,然後再真正寫到對應目錄的硬碟上, * 按理來說當上傳一個檔案時,其實是上傳了兩份,第一個是以 .tem 格式的 * 然後再將其真正寫到對應目錄的硬碟上 */ //獲取檔案需要上傳到的路徑 String path = request.getRealPath("/upload") + "//"; System.out.println("path=" + path); File dir = new File(path); if (!dir.exists()) {//資料夾不存在,建立 dir.mkdir(); } factory.setRepository(dir); //設定快取的大小,當上傳檔案的容量超過該快取時,直接放到暫時儲存室 factory.setSizeThreshold(1024 * 1024); //高水平的API檔案上傳處理 ServletFileUpload upload = new ServletFileUpload(factory); upload.setHeaderEncoding("UTF-8");//解決上傳"檔名"的中文亂碼 try { List<FileItem> list = upload.parseRequest(request); if(list==null || list.isEmpty()){ code = -1; msg="沒有可儲存的檔案"; this.outPut(response,null); return; } int fileListLen = 0; for (FileItem item : list) { //如果fileitem中封裝的是普通輸入項的資料(輸出名、值) if (item.isFormField()) { //獲取表單的屬性名字 String name = item.getFieldName(); //獲取使用者具體輸入的字串 String value = item.getString("UTF-8"); request.setAttribute(name, value); System.out.println("name=" + name + ",value=" + value); } else { //如果fileItem中封裝的是上傳檔案,得到上傳的檔名稱 String fileName = item.getName();//上傳檔案的名 //多個檔案上傳輸入框有空 的 異常處理 if(fileName==null||"".equals(fileName.trim())){ //去空格是否為空 continue;// 為空,跳過當次迴圈, 第一個沒輸入則跳過可以繼續輸入第二個 } //不同的瀏覽器提交的檔名是不一樣的,有些瀏覽器提交上來的檔名是帶有路徑的,如: c:\a\b\1.txt,而有些只是單純的檔名,如:1.txt //擷取留最後一個"\"之後,+1截取向右移一位 fileName = fileName.substring(fileName.lastIndexOf("\\")+1); String fileType = fileName.substring(fileName.lastIndexOf(".")); System.out.println(fileName); fileName = (String) request.getAttribute("FIDCARD"); if(fileListLen>0){ fileName = fileName+fileListLen; } fileName+=fileType; fileListLen++; this.saveFile(item, path, fileName); } } } catch (FileUploadException fue) { fue.printStackTrace(); code = -1; msg = "操作失敗!"; errMsg = fue.getMessage(); } catch (Exception e) { e.printStackTrace(); code = -1; msg = "操作失敗!"; errMsg = e.getMessage(); } Map result = new HashMap(); result.put("status", code); result.put("msg", msg); result.put("errMsg", errMsg); this.outPut(response,result); } /** * * @param fileItem * @param path * @param fileName 帶檔案字尾 如:"名字.png" String fileName = request.getAttribute("FIDCARD") + ".png"; * @return */ private void saveFile(FileItem fileItem,String path,String fileName) throws IOException{ //拼接上傳路徑。存放路徑+上傳的(自定義)檔名 String destPath = path + fileName; System.out.println("destPath=" + destPath); InputStream in = fileItem.getInputStream();//獲取item中的上傳檔案的輸入流 //真正寫到磁碟上 File file = new File(destPath); OutputStream out = new FileOutputStream(file); int length = -1; byte[] buf = new byte[1024];//建立一個緩衝區 while ((length = in.read(buf)) != -1) { //在buf陣列中取出資料寫到(輸出流)磁碟上 out.write(buf, 0, length); } in.close(); out.close(); //刪除臨時檔案 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } fileItem.delete();//刪除處理檔案上傳時生成的臨時檔案 } /** * 返回json資料 * @param response * @throws ServletException * @throws IOException */ private void outPut(HttpServletResponse response,Map result) throws ServletException,IOException{ PrintWriter printWriter = response.getWriter(); // response.setHeader("Content-type", "text/html;charset=UTF-8"); // response.setContentType("text/html;charset=UTF-8"); HashMap<String, Object> res = new HashMap<String, Object>(); res.put("status", code); res.put("msg", msg); res.put("errMsg", errMsg); res.put("data", result); printWriter.write(JSONObject.fromObject(res).toString()); PrintWriter out = response.getWriter(); out.flush(); out.close(); } /** * Initialization of the servlet. <br> * * @throws ServletException * if an error occurs */ public void init() throws ServletException { // Put your code here } }