Java Servlet實現檔案上傳並讀取Zip壓縮包中檔案的真實型別
阿新 • • 發佈:2018-12-17
1.上傳檔案servlet
PS: 使用ant.jar中的 org.apache.tools.zip.ZipEntry 物件,防止亂碼
package com.chenl.servlets; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.Enumeration; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.tools.zip.ZipEntry; import org.apache.tools.zip.ZipFile; import com.chenl.util.FileType; import com.chenl.util.FileUtil; /** * Servlet implementation class UploadServlet */ @WebServlet("/UploadServlet") public class UploadServlet extends HttpServlet { private static final long serialVersionUID = 1L; // 上傳檔案儲存目錄 private static final String UPLOAD_DIRECTORY = "upload"; // 上傳配置 private static final int MEMORY_THRESHOLD = 1024 * 1024 * 3; // 3MB private static final int MAX_FILE_SIZE = 1024 * 1024 * 40; // 40MB private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50; // 50MB private static String today; private static int iosCount; private static int androidCount; /** * 上傳資料及儲存檔案 */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 檢測是否為多媒體上傳 if (!ServletFileUpload.isMultipartContent(request)) { // 如果不是則停止 PrintWriter writer = response.getWriter(); writer.println("Error: 表單必須包含 enctype=multipart/form-data"); writer.flush(); return; } // 配置上傳引數 DiskFileItemFactory factory = new DiskFileItemFactory(); // 設定記憶體臨界值 - 超過後將產生臨時檔案並存儲於臨時目錄中 factory.setSizeThreshold(MEMORY_THRESHOLD); // 設定臨時儲存目錄 factory.setRepository(new File(System.getProperty("java.io.tmpdir"))); ServletFileUpload upload = new ServletFileUpload(factory); // 設定最大檔案上傳值 upload.setFileSizeMax(MAX_FILE_SIZE); // 設定最大請求值 (包含檔案和表單資料) upload.setSizeMax(MAX_REQUEST_SIZE); // 中文處理 upload.setHeaderEncoding("UTF-8"); // 構造臨時路徑來儲存上傳的檔案 // 這個路徑相對當前應用的目錄 String uploadPath = request.getServletContext().getRealPath("./") + File.separator + UPLOAD_DIRECTORY; String userAgent = request.getHeader("user-agent").toLowerCase(); String ip = request.getRemoteAddr(); // 如果目錄不存在則建立 File uploadDir = new File(uploadPath); if (!uploadDir.exists()) { uploadDir.mkdir(); } try { List<FileItem> formItems = upload.parseRequest(request); if (formItems != null && formItems.size() > 0) { for (FileItem item : formItems) { if (!item.isFormField()) { String fileName = new File(item.getName()).getName(); String extName = fileName.substring(fileName.lastIndexOf("."));// 獲取檔案的字尾名 fileName = validateUserAgent(userAgent, fileName, extName); if (fileName == null) { throw new Exception("userAgent error : " + fileName); } boolean simpleValidate = simpleExtValidate(extName); if (simpleValidate == false) { throw new Exception("ext error " + fileName); } String filePath = uploadPath + File.separator + fileName; File storeFile = new File(filePath); System.out.println(filePath); // 儲存檔案到硬碟 item.write(storeFile); boolean result = validateRealFileType(fileName); if (!result) { File file = new File("D:\\java_workspace\\UploadImagesDemo\\WebContent\\upload\\" + fileName); file.delete(); System.out.println("del file: " + fileName); throw new IOException("validate error " + fileName); } } } // request.setAttribute("message", // "{'code':'0','message':'success'}"); response.setContentType("application/json"); response.getWriter().print("{\"files\":[{}]}"); response.getWriter().flush(); response.getWriter().close(); } } catch (Exception ex) { System.out.println(ex); printError(ip, ex.getMessage()); response.getWriter().print("{'code':'200','files':" + ex.getMessage() + "}"); response.getWriter().flush(); response.getWriter().close(); } } private String validateUserAgent(String userAgent, String fileName, String extName) { SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd"); String timeString = format.format(new Date()); if (!timeString.equals(today)) { today = timeString; iosCount = 0; androidCount = 0; } if (userAgent != null) { if (userAgent.contains("iphone")) { fileName = "ios-" + timeString + "-" + (iosCount++) + extName; return fileName; } else if (userAgent.contains("android")) { fileName = "android-" + timeString + "-" + (androidCount++) + extName; return fileName; } } return null; } private boolean simpleExtValidate(String extName) { extName = extName.toLowerCase(); String[] extArr = { ".png", ".jpg", ".jpeg", ".zip" }; List<String> extList = Arrays.asList(extArr); return extList.contains(extName); } private boolean validateRealFileType(String fileName) throws IOException{ File file = new File("D:\\java_workspace\\UploadImagesDemo\\WebContent\\upload\\" + fileName); FileType type = FileUtil.getType(file); List<FileType> types = Arrays.asList(FileType.values()); if(types.contains(type)){ if(type == FileType.ZIP){ boolean pass = true; ZipFile zipFile = new ZipFile(file,"gbk"); Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zipFile.getEntries(); while(entries.hasMoreElements()){ ZipEntry ze = entries.nextElement(); if(!ze.isDirectory()){ byte[] b = new byte[28]; InputStream input = zipFile.getInputStream(ze); if(input != null){ input.read(b, 0, 28); input.close(); FileType fileType = FileUtil.getType(FileUtil.bytesToHexString(b)); System.out.println("name= " + ze.getName() + " fileType = "+fileType); if(!(fileType == FileType.PNG || fileType == FileType.JPEG)){ pass = false; break; } }else{ System.err.println("InputStream == null name= " + ze.getName()); } } } zipFile.close(); return pass; }else{ return true; } } return false; } private void printError(String ip, String msg) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String wg = "ip地址: " + ip + " " + format.format(new Date()) + " " + msg; System.err.println(wg); } }
2.根據檔案頭判斷檔案真實型別
package com.chenl.util; public enum FileType { JPEG("FFD8FF"), PNG("89504E47"), ZIP("504B0304"); private String value = ""; private FileType(String value){ this.value = value; } public String getValue(){ return value; } public void setValue(String value){ this.value = value; } }
package com.chenl.util; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; public class FileUtil { public static String bytesToHexString(byte[] src) { StringBuilder buff = new StringBuilder(); if (src == null || src.length <= 0) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; String hv = Integer.toHexString(v).toUpperCase(); if (hv.length() < 2) { buff.append(0); } buff.append(hv); } return buff.toString(); } private static String getFileContent(File file) throws IOException { byte[] b = new byte[28]; InputStream input = new FileInputStream(file); input.read(b, 0, 28); input.close(); return bytesToHexString(b); } public static FileType getType(File file) throws IOException { String fileHead = getFileContent(file); if (fileHead == null || fileHead.length() == 0) { return null; } fileHead = fileHead.toUpperCase(); FileType[] fileTypes = FileType.values(); for (FileType fileType : fileTypes) { if (fileHead.startsWith(fileType.getValue())) { return fileType; } } return null; } public static FileType getType(String fileHead) throws IOException { if (fileHead == null || fileHead.length() == 0) { return null; } fileHead = fileHead.toUpperCase(); FileType[] fileTypes = FileType.values(); for (FileType fileType : fileTypes) { if (fileHead.startsWith(fileType.getValue())) { return fileType; } } return null; } }