2013年9月17日星期二

There are no third-party components can not handle file uploads ( pure Servlet)

 This post last edited by the sunbo624 on 2013-09-16 15:57:49
recently to write a thing , does not depend on other third-party components that handle file uploads , and is a multi- file upload .
only with Servlet API, can not use apache or other those components , which experts have done a similar function and success, help !
I think it must have the means , or in the absence of those components when it came to how to do file upload needs .
------ Solution ---------------------------------------- ----
I am here to answer too .

http://bbs.csdn.net/topics/390154611


------ For reference only ---------------------------------- -----

UploadBytes What is this class
------ For reference only --------------------- ------------------
many examples online right
------ For reference only ------------ ---------------------------
really small basically use a third-party
--- --- For reference only ---------------------------------------

UploadBytes What is this class  

is a utility class , as follows .


public class UploadBytes {

    //文件名的标志位
    public static final String SIGN_FILENAME = "filename=\"";
    //表单域名称的标志位
    public static final String FORM_NAME = "name=\"";
    //以引号结束的标志位(文件名和表单域名称后的内容)
    public static final String QUOTE_FLAG = "\"";
    //含文件名的表单域的上传文件类型 Content-type
    private final static String CONTENT_TYPE = "Content-Type:";
    //自动换行符(上传文件类型名称后面的内容 实际上传文件内容之前的换行符)
    private final static String AUTO_LINE = "\r\n\r\n";
    private static final String SIGN_MULTIDATA = "multipart/form-data";
    //默认编码
    private final static String DEFAULT_ENCODING = "iso8859_1";

    /**
     * buff为当前已经读取的上传流字节
     * boundary为HTTP头信息中的Content-Type指定的当前域的分隔符的字节数组
     * 处理思想即找到一组成对的boundary,那么其中的字节即为表单域的数据.
     * @param boundary 分隔符
     * @param buff 输出流
     * @return 各分隔符之间的字节列表
     * @throws Exception
     */
    public static List<byte[]> findFiled(byte[] boundary,
            ByteArrayOutputStream buff)
            throws Exception {

        //当前的数据连成对的boundary长度都不够,直接返回。
        if (buff.size() < boundary.length * 2) {
            return Collections.emptyList();
        } else {
            byte[] data = buff.toByteArray();//当前数据

            List<byte[]> fileds = new ArrayList<byte[]>();
            int point = 0;//当前指针位置
            int alertStart = 0;//最近一次警戒区的位置
            boolean alert = false;//是否处于警戒区
            int treated = 0;//已经处理的字节长度

            while (true) {
                if (!alert && data.length - point < boundary.length * 2) {
                    break;
                } else if (alert && data.length - point < boundary.length) { 
                    break;
                }

                if (isBytes(data, boundary, point)) {
                    if (!alert) { //start line
                        alert = true;
                        alertStart = point + boundary.length;
                        point = alertStart;
                    } else { //end line
                        byte[] filed;
                        filed = Arrays.copyOfRange(data, alertStart, point);
                        treated += (point - alertStart + boundary.length);

                        fileds.add(filed);
                        alert = false;
                    }
                } else {
                    point++;
                }
            }

            if (fileds.size() > 0) {
                buff.reset();
                buff.write(data, treated, data.length - treated);
                return fileds;
            }

            return Collections.emptyList();
        }

    }

    /**
     * 根据解析上传文件的所有分隔符之间的字节数组列表
     * 来获取各个文件上传的文件名所在表单域的字节数组列表
     * 即含"filename="的表单域字节数组
     * @param filesByte 所有分隔符之间的字节数组列表
     * @param charset 上传文件的字符集
     * @return 各个文件上传的文件名所在表单域的字节数组列表
     */
    public static List<byte[]> getFilesByteList(
            List<byte[]> filesByte, String charset)
            throws UnsupportedEncodingException {
        List<byte[]> fieldFilesByte = new ArrayList<byte[]>();

        byte[] fileName = SIGN_FILENAME.getBytes(charset);
        for (int i = 0; i < filesByte.size(); i++) {
            byte[] bs = filesByte.get(i);
            int point = 0;
            while (true) {
                if (bs.length - point < fileName.length) {
                    break;
                }
                if (isBytes(bs, fileName, point)) {
                    fieldFilesByte.add(bs);
                    break;
                } else {
                    point++;
                }
            }
        }

        return fieldFilesByte;
    }

    /**
     * 根据获取上传文件实际域的数据的字节 获取实际域数据
     * @param fieldByte 实际域的数据的字节
     * @param charset 上传文件的编码
     * @return 实际域的数据
     */
    public static Field getField(byte[] fieldByte, String charset)
            throws UnsupportedEncodingException, IOException {
        Field field = new Field();

        String fileNameStr = getFieldStr(fieldByte, charset, SIGN_FILENAME,
                QUOTE_FLAG);

        field.setFieldName(fileNameStr);
        String fileName = "";
        if (fileNameStr != null && !fileNameStr.isEmpty()) {
            fileName = getExtensionName(fileNameStr);
        }
        field.setFileName(fileName);

        String fileType = getFieldStr(fieldByte, charset, CONTENT_TYPE,
                AUTO_LINE);
        field.setContentType(fileType);

        byte[] realFileBytes = getRealFileByte(fieldByte, charset);
        field.setFieldData(realFileBytes);

        return field;
    }

    /**
     * 根据域数据获取域中标志的名称
     * @param fieldByte 域数据
     * @param charset 编码
     * @param nameFlag 名称的标志
     * @param endFlag 以该标志位结束的内容
     * @return 名称
     */
    private static String getFieldStr(byte[] fieldByte, String charset,
            String nameFlag, String endFlag)
            throws UnsupportedEncodingException {

        byte[] fileNameByte = nameFlag.getBytes(charset);
        int point = 0;
        while (true) {
            if (fieldByte.length - point < fileNameByte.length) {
                break;
            }
            if (isBytes(fieldByte, fileNameByte, point)) {
                break;
            } else {
                point++;
            }
        }

        int pos = point + fileNameByte.length;

        //截取从名称开始到内容结束的部分的字节数组
        byte[] fileStart = Arrays.copyOfRange(fieldByte, pos, fieldByte.length);

        //从文件名开始 第一个引号 " 出现的位置 (即为文件名后面的第一个引号)
        byte[] quoteBytes = endFlag.getBytes(charset);
        int point1 = 0;
        while (true) {
            if (fileStart.length - point1 < quoteBytes.length) {
                break;
            }
            if (isBytes(fileStart, quoteBytes, point1)) {
                break;
            } else {
                point1++;
            }
        }

        //名称开始到名称结束的字节数组
        byte[] nameBytes = Arrays.copyOfRange(fieldByte, pos, pos + point1);
        if (nameBytes == null || nameBytes.length == 0) {
            return null;
        }
        String result = new String(nameBytes, charset);
        //若结果前后含有空格,则去掉前后的空格
        result = result.trim();
        return result;
    }

    /**
     * 根据带文件名的文件表单域字节获取实际要上传的字节内容
     * @param fieldByte 带文件名的文件表单域字节
     * @param charset 文件的字符集
     * @return 实际要上传的字节内容
     */
    public static byte[] getRealFileByte(byte[] fieldByte, String charset)
            throws UnsupportedEncodingException, FileNotFoundException,
            IOException {

        //自动换行开始的位置
        byte[] autoLineByte = AUTO_LINE.getBytes(charset);
        int point = 0;
        while (true) {
            if (fieldByte.length - point < autoLineByte.length) {
                break;
            }
            if (isBytes(fieldByte, autoLineByte, point)) {
                break;
            } else {
                point++;
            }
        }

        //上传文件的实际内容(自动换行结束的位置开始,内容的结束有一个换行符)
        byte[] realFileByte = Arrays.copyOfRange(fieldByte,
                point + autoLineByte.length, fieldByte.length - 2);

        return realFileByte;
    }

    /**
     * 比较源数据中是否有与给定的字节数组匹配的数据
     * @param data 源数据
     * @param byteGiven 要比较的数据
     * @param point 当前指针所在的位置
     * @return
     */
    public static boolean isBytes(byte[] data, byte[] byteGiven, int point) {
        for (int i = 0; i < byteGiven.length; i++) {
            if (data[point + i] != byteGiven[i]) {
                return false;
            }
        }
        return true;
    }

    /**
     * 获取上传文件的字符集
     * @param request 请求
     * @return 如果设置字符集的话 则返回字符集,否则 返回默认的字符集
     */
    public static String getCharset(HttpServletRequest request) {
        CharsetParser charsetParser = new CharsetParser();
        String contentType = request.getContentType();
        String charset = charsetParser.getCharset(contentType, ';');
        if (charset == null || charset.isEmpty()) {
            charset = DEFAULT_ENCODING;
        }
        return charset;
    }

    /**
     * 获取请求的信息
     * @param request 请求
     * @return 请求信息byte数组
     * @throws IOException
     */
    public static byte[] getContentBytes(HttpServletRequest request) throws
            IOException {

        InputStream sis = request.getInputStream();

        int dataLength = request.getContentLength();
        //保存上传图片的数据
        byte[] dataBytes = new byte[dataLength];
        int byteRead = 0;
        int totalBytes = 0;
        //上传的数据保存在byte数组
        while (totalBytes < dataLength) {
            byteRead = sis.read(dataBytes, totalBytes, dataLength);
            totalBytes += byteRead;
        }

        sis.close();

        return dataBytes;
    }

    /**
     * 取得数据的分隔字符串
     * @param request 请求
     * @return 数据的分隔字符串
     */
    public static String getBoundaryStr(HttpServletRequest request) {
        String contentType = request.getContentType();
        int lastIndex = contentType.lastIndexOf("=");

        //取得数据的分隔字符串
        String boundaryStr = "--" + contentType.substring(lastIndex + 1,
                contentType.length());


        return boundaryStr;
    }

    /**
     * 获取上传文件的扩展名
     * @param fileName 文件名
     * @return 文件名的扩展名
     */
    public static String getExtensionName(String fileName) {
        int format = fileName.lastIndexOf(".");
        String extensionName = "";

        if (format >= 0) {
            extensionName = fileName.substring(format);
        }
        return extensionName;
    }

    /**
     * 判断上传文件类型,如果是multipart/form-data,则返回true,否则返回fase
     * @param request 请求
     * @return boolean
     */
    public static boolean getContentTypeFlag(HttpServletRequest request) {
        String contentType = request.getContentType();
        if (contentType != null && !contentType.isEmpty()) {
            if (contentType.indexOf(SIGN_MULTIDATA) >= 0) {
                return true;
            }
        }
        return false;
    }
}


------ For reference only ---------------------------------- -----
search servlet bulk upload more than N it ! !
------ For reference only -------------------------------------- -

can be found to also be used in this help ?
------ For reference only -------------------------------------- -

UploadBytes What is this class          
  
is a utility class , as follows .   
  
 

You 've done the same function right, I follow your post in the request that information , the string analysis, the results will come out , but the Chinese garbled, you come across it
----- - For reference only ---------------------------------------
stay mailboxes ; send items to you
------ For reference only -------------------------------- -------


I realized , though your code though useless , but the thing I read is to read the post request information only to achieve, in the Whole to you !

没有评论:

发表评论