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);
            }
        }

解决方案 »

  1.   

            int size = 0;
            try {
                int data_start = content_start;
                while (true) {
                    int boundary_end = search(data, data_start, boundary_tag);
                    if (boundary_end == -1) {
                        if (length == 0) {
                            //System.out.println("buffer:" + new String(data, data_start, readlen));
                            return fi.fail("ERR_DATA_BOUNDARY", "Cannot get the boundary end");
                        }                    int writelen = readlen - data_start - REMAIN_SIZE;
                        if (fi.isFile) {
                            try {
                                fo.write(data, data_start, writelen);
                                //System.out.println("Write " + writelen + " bytes");
                            } catch (IOException ioe) {
                                return fi.fail("ERR_WRITE_FILE", "Write data to file error");
                            }
                        }
                        size += writelen;
                        System.arraycopy(data, readlen - REMAIN_SIZE, data, 0, REMAIN_SIZE);                    readlen = (length > READ_BUFSIZE)? READ_BUFSIZE : length;
                        if (readFully(in, data, REMAIN_SIZE, readlen) == -1) {
                            return fi.fail("ERR_READ_NETWORK_DATA", "Read data from network error");
                        }                    //System.out.println("Read " + readlen + " bytes");
                        length -= readlen;
                        readlen += REMAIN_SIZE;
                        data_start = 0;
                    } else {
                        int writelen = boundary_end - data_start;
                        if (fi.isFile) {
                            try {
                                fo.write(data, data_start, writelen);
                                //System.out.println("Write " + writelen + " bytes over");
                            } catch (IOException ioe) {
                                return fi.fail("ERR_WRITE_FILE", "Write data to file error");
                            }
                        }
                        size += writelen;
                        fi.remain = readlen - boundary_end;
                        System.arraycopy(data, boundary_end, data, 0, fi.remain);
                        break;
                    }
                }
            } finally {
                if (fo != null) {
                    try {
                        fo.close();
                    } catch (IOException ioe) {
                        return fi.fail("ERR_CLOSE_FILE", "Close file error");
                    }
                }
            }        fi.size = size;
            return fi;
        }    private boolean saveFile(HttpServletRequest request) throws UnsupportedEncodingException {
            String contentType = request.getContentType();
            //System.out.println("ContentType=" + contentType);        if (contentType == null || !contentType.startsWith("multipart/form-data")) {
                afterUploadFail("ERR_CONTENT_TYPE", "ContentType not multipart/form-data\n");
                return false;
            }        byte[] boundary = contentType.substring(contentType.indexOf("boundary=") + 9).getBytes(); 
            byte[] boundary_tag = merge(BOUNDARY_PREFIX, boundary);        int length = request.getContentLength();
            System.out.println("Total stream size: " + length);
            
            InputStream in = null;
            try {
                in = request.getInputStream();
            } catch (IOException ioe) {
                afterUploadFail("ERR_READ_NETWORK_DATA", "Get input stream error");
                return false;
            }        byte[] data = new byte[DEFAULT_BUFSIZE];
            data[0] = CR;
            data[1] = LF;
            int remain = 2;        int index = 1;
            while (true) {
                FileInfo fi = saveOneFile(request, in, index, length, data, remain, boundary_tag);
                if (!fi.success) {
                    afterUploadFail(index, fi.errcode, fi.errmsg);
                    return false;
                } else if (fi.isFile) {
                    afterUploadSuccess(index, fi.name, fi.fileName);
                    index++;
                    System.out.println("Success upload file " + fi.fileName);
                    //System.out.println("file size " + fi.size);
                } else {
                    break;
                }            length -= fi.size;
                remain = fi.remain;            if (length <= 0) {
                    break;
                }            //System.out.println("length remain " + length);
                //System.out.println("data remain " + remain);
            }        return true;
        }    public void init() throws ServletException {
            try {
                upload_base_path = "/home/vloaner/";
                System.out.println("FileUploadServlet init params upload path:" + upload_base_path);
            } catch(Exception e) {
               e.printStackTrace(); 
            }    }    public void doPost(HttpServletRequest request, HttpServletResponse response) {
            boolean success = false;
            try {
                success = saveFile(request);
            } catch (UnsupportedEncodingException e1) {
                e1.printStackTrace();
            }
            try {
                request.setCharacterEncoding("UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            response.setHeader("Pragma","No-cache"); 
            response.setHeader("Cache-Control","no-cache"); 
            response.setDateHeader("Expires", 0); 
            response.setContentType("text/html;charset=UTF-8");        String html = 
                "<script language='JavaScript'>\n" +
                "    if (parent._on_upload_over) {\n" +
                "        parent._on_upload_over(" + success + ");\n" +
                "    }\n" +
                "</script>\n";        try {
                PrintWriter out = response.getWriter();
                out.print(html);
                response.flushBuffer();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }    public void doGet(HttpServletRequest request, HttpServletResponse response) {
            throw new RuntimeException("File upload only support post");
        }
    }
      

  2.   

    我遇到过同样的问题,我的处理办法是:先用jdk里面的加密类进行加密,后解密