1. 程式人生 > >使用Servlet從微信小程式請求的檔案流獲取檔案內容和表單資料

使用Servlet從微信小程式請求的檔案流獲取檔案內容和表單資料

說明:專案中用到微信小程式上傳檔案,發現檔案放在流中,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
	}

}