http文件上传的总结

来源:互联网 发布:淘宝账户被限制登录了 编辑:程序博客网 时间:2024/06/05 07:34

7.21
最近有人问我怎么进行文件上传,然后我就想到平常我们后台接受的文件要么就用各种文件上传接受jar包直接操作,要么就用struts2直接接收成File(话说File并不能指向内存中的文件内容,那这个File到底存在哪里是个问题)。所以我就想看看文件上传的原理,然后自己去实现下文件接收。
一、http文件报文的格式

-----------------------------92901418813201Content-Disposition: form-data; name="title"asd-----------------------------92901418813201Content-Disposition: form-data; name="image"; filename="1320140315.JPG"Content-Type: image/jpeg文件-----------------------------92901418813201-- 

这是我找到的某http报文,这是request获取的inputstream直接获得的报文,还有request中的头部有两个重要的信息:
Content-Type:multipart/form-data;boundary=—————————7d33a816d302b6
Content-Length: 424,
解释下 Content-Type中的boundary是当type是multipart时特有的,用来分割内容,据说是自动生成,并且报文内容中不会有和他一样的字符串。
Content-Length是刚刚request获得的inputstream的报文的长度,是总长度
然后报文中格式是:

--boundary+\r\n         //注意http报文中换行是\r\n文件头信息+\r\n(可能还有头信息需要换行)\r\n信息内容+\r\n--boundary||如果是报文结尾的话就是--boundary--

所以根据这个报文格式进行处理,就可以获得文件了。
二、代码
我的截取方法很简单,现将报文接收到byte[]中,再转成String,按照boundary截取后再按格式截取,就获得文件,再转成byte[],
这里我被编码方式坑了一次,以前都没注意过编码方式的问题

package com.yc.servlet;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Set;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class Userservlet extends HttpServlet {    private static final long serialVersionUID = 1L;    String Path = "E:/";    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        doPost(request, response);    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws IOException {        Map<String, byte[]> map = parse(request);        Set<String> filenamesset = map.keySet(); // 遍历获得所有文件名        for (String name : filenamesset) { // 对文件名遍历 进行存储            File tempfile = new File(Path + new Date().getTime() + name);            FileOutputStream out = new FileOutputStream(tempfile);            out.write(map.get(name)); // 读入到磁盘,             out.flush();            out.close();        }    }    /*     *      * map 的存储: 只存储文件 文件名就是键 文件byte[] 是值        这个方法过滤不是multipart的报文     */    public Map<String, byte[]> parse(HttpServletRequest request)//            throws IOException {        int length = request.getContentLength();        String Type = request.getContentType();        String boundary = Type.substring(Type.indexOf("boundary") + 9,Type.length());//获得boundary        InputStream in = request.getInputStream(); // 获取输入流        if (Type.startsWith("multipart/form-data;")) { // 判断是多数据上传            return subbyte(in, boundary, length);        } else {            throw new RuntimeException("非多数据情况");        }    }    /*     * 这个方法进行截取     * */    public Map<String, byte[]> subbyte(InputStream in, String boundary, int length) throws IOException {        Map<String, byte[]> map = new HashMap<String, byte[]>();        byte[] buffer = new byte[length];        in.read(buffer);        String contentbuffer = new String(buffer, "iso8859-1");//为什么是iso8859-1那,这里我被坑了很久,下一篇写字符编码讲解为什么        System.out.println(contentbuffer);        String[] contents = contentbuffer.split("(" + "--" + boundary + "--"+ ")|(" + "--" + boundary + ")");//按照   boundary分割          for (String c : contents) {            if (c.indexOf("filename") != -1) {                String name = c.substring(c.indexOf("filename=") + 10,c.indexOf("\"", c.indexOf("filename=\"") + 10));                String file1 = c.substring(c.indexOf("\r\n\r\n") + 4);                file1 = file1.substring(0, file1.length() - 2);                                 byte[] file2 = file1.getBytes("iso8859-1");                map.put(name, file2);            }        }        return map;    }}

这个处理方法并不好,我觉得应该还有某种更好的流操作,但是我流操作学的并不好,找不到一个可以进行截取的流,等我复习了流操作说不定可以改善下

0 0