日期:2014-05-20 浏览次数:20950 次
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.wk.util.StringUtil; @SuppressWarnings("serial") public class FileUploadServlet extends HttpServlet { public static final byte CR = 0x0D; public static final byte LF = 0x0A; public static final byte DASH = 0x2D; protected static final int REMAIN_SIZE = 64; protected static final int DEFAULT_BUFSIZE = 4096; protected static final int READ_BUFSIZE = DEFAULT_BUFSIZE - REMAIN_SIZE; protected static final byte[] HEADER_SEPARATOR = {CR, LF, CR, LF}; protected static final byte[] FIELD_SEPARATOR = {CR, LF}; protected static final byte[] STREAM_TERMINATOR = {DASH, DASH}; protected static final byte[] BOUNDARY_PREFIX = {CR, LF, DASH, DASH}; private static String upload_base_path; protected boolean equals(byte[] b1, int start1, byte[] b2, int start2, int length) { if (b1.length - start1 < length) { return false; } if (b2.length - start2 < length) { return false; } for (int i = 0; i < length; i++) { if (b1[start1 + i] != b2[start2 + i]) { return false; } } return true; } protected int search(byte[] b, int start, String str) { return search(b, start, str.getBytes()); } protected int search(byte[] b, int start, byte[] s) { int length = s.length; byte first = s[0]; for (int i = start, total = b.length - length; i <= total; i++) { if (b[i] == first && equals(b, i, s, 0, length)) { return i; } } return -1; } protected byte[] merge(byte[]... bs) { if (bs == null) { return null; } int total = 0; for (byte[] b : bs) { total += b.length; } byte[] newb = new byte[total]; int offset = 0; for (byte[] b : bs) { System.arraycopy(b, 0, newb, offset, b.length); offset += b.length; } return newb; } protected int readFully(InputStream in, byte[] buff, int offset, int length) { int total = 0; while (true) { try { int readlen = in.read(buff, offset, length); if (readlen == -1) { return 0; } total += readlen; if (readlen == length) { return total; } offset += readlen; length -= readlen; } catch (IOException ioe) { return -1; } } } protected void afterUploadSuccess(int index, String name, String fileName) { } protected void afterUploadFail(String errcode, String errmsg) { afterUploadFail(0, errcode, errmsg); } protected void afterUploadFail(int index, String errcode, String errmsg) { if (index == 0) { System.out.println(errcode + ":" + errmsg); } else { System.out.println("Upload file " + index + " error:"); System.out.println(errcode + ":" + errmsg); } } protected String getUploadPath(HttpServletRequest request) { String saveFilePath = request.getParameter("uploadPath"); if (saveFilePath == null) { saveFilePath="upload"; } String uploadPath; if (StringUtil.isEmpty(upload_base_path)) { uploadPath = getServletContext().getRealPath(saveFilePath); } else { uploadPath = upload_base_path + saveFilePath; } return uploadPath; } protected String getUploadFileName(HttpServletRequest request, int index, String name, String fileName) throws UnsupportedEncodingException { String[] fnames = request.getParameterValues("fileName"); String fname = fileName; if (fnames != null && fnames.length >= index) { fname = fnames[index-1]; } if (fname == null) { fname = ""; } fname = new String(fname.getBytes("iso-8859-1"),"UTF-8"); char sep = (fname.indexOf('/') >= 0) ? '/' : '\\'; int pos = fname.lastIndexOf(sep); String newFileName; if (pos < 0) { newFileName = fname; } else { newFileName = fname.substring(pos + 1); } return getUploadPath(request) + File.separatorChar + newFileName; } private String getNameFromDisposition(byte[] disposition) { return getField(disposition, "name="); } private String getFileNameFromDisposition(byte[] disposition) { return getField(disposition, "filename="); } private String getField(byte[] disposition, String field) { int field_start = search(disposition, 0, field); if (field_start == -1) { return null; } String value; field_start += field.length(); int field_end = search(disposition, field_start, ";"); if (field_end == -1) { value = new String(disposition, field_start, disposition.length - field_start).trim(); } else { value = new String(disposition, field_start, field_end - field_start).trim(); } value = value.replaceAll("\"", ""); return value; } static class FileInfo { int index; // 第几个文件,从1开始 boolean isFile; // 是否是文件 String fileName; // 文件名 String name; // input的名称 int size; // 文件的大小 int remain; // 这次读的但是没有处理完成的数据 boolean success; // 是否保存成功 String errcode; // 错误编号 String errmsg; // 错误信息 FileInfo fail(String errcode, String errmsg) { this.success = false; this.errcode = errcode; this.errmsg = errmsg; return this; } } private FileInfo saveOneFile(HttpServletRequest request, InputStream in, int index, int length, byte[] data, int remain, byte[] boundary_tag) throws UnsupportedEncodingException { FileInfo fi = new FileInfo(); fi.index = index; fi.success = true; int readlen = (length > (DEFAULT_BUFSIZE-remain))? (DEFAULT_BUFSIZE-remain) : length; if (readFully(in, data, remain, readlen) == -1) { return fi.fail("ERR_READ_NETWORK_DATA", "Read data from network error"); } length -= readlen; readlen += remain; // System.out.println("buffer:" + new String(data, 0, readlen)); // 处理boundary start if (!equals(data, 0, boundary_tag, 0, boundary_tag.length)) { return fi.fail("ERR_DATA_BOUNDARY", "Data not start with the boundary"); } if (equals(data, boundary_tag.length, STREAM_TERMINATOR, 0, STREAM_TERMINATOR.length)) { return fi; } // 处理文件名 int content_disposition_start = search(data, 0, "Content-Disposition"); if (content_disposition_start == -1) { return fi.fail("ERR_DATA_DISPOSITION", "Cannot get the content disposition"); } int field_end = search(data, content_disposition_start, FIELD_SEPARATOR); if (field_end == -1) { return fi.fail("ERR_DATA_DISPOSITION", "Cannot get the content disposition"); } byte[] disposition = new byte[field_end - content_disposition_start]; System.arraycopy(data, content_disposition_start, disposition, 0, field_end - content_disposition_start); String fname = getFileNameFromDisposition(disposition); if (fname != null && !fname.equals("")) { fi.isFile = true; } else { fi.isFile = false; fname = ""; } String name = getNameFromDisposition(disposition); fname = getUploadFileName(request, index, name, fname); System.out.println(fname+"++++++++++++++++++++++++++++++++="); fi.fileName = fname; fi.name = name; //System.out.println("fname="+fname); // 到达开始处 int content_start = search(data, 0, HEADER_SEPARATOR); if (content_start == -1) { return fi.fail("ERR_DATA_CONTENT_START", "Cannot get the content start"); } content_start += HEADER_SEPARATOR.length; // 打开文件 FileOutputStream fo = null; if (fi.isFile) { try { fo = new FileOutputStream(fname); } catch (IOException ioe) { ioe.printStackTrace(); return fi.fail("ERR_FILE_CREATE", "cannot create file: " + fname); } }