http文件上传的总结

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

-----------------------------92901418813201
Content-Disposition: form-data; name="title"

asd
-----------------------------92901418813201
Content-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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: C HTTP文件上传下载是通过使用HTTP协议进行文件传输的一种方法。它通常用于从一个计算机将文件上传到另一个计算机或从服务器下载文件。 在文件上传过程中,客户端通过HTTP POST请求将文件发送给服务器。服务器端接收到文件后,可以将其保存到指定的位置,并返回相应的信息给客户端,确认文件上传成功。 在文件下载过程中,客户端通过HTTP GET请求从服务器获取文件。服务器端根据请求的文件路径找到相应的文件,并将文件的内容返回给客户端进行下载。 文件上传下载通常需要用到HTTP的multipart/form-data请求格式,该格式可以将文件和其他表单数据一起发送到服务器。 在实际应用中,我们可以使用一些开源的库来简化文件上传下载的过程,例如Python中的requests库、Java中的Apache HttpClient、JavaScript中的axios等。这些库提供了一些便捷的方法和函数,可以帮助我们实现文件的上传下载功能。 除了使用HTTP协议外,还可以使用其他协议来进行文件上传下载,例如FTP(File Transfer Protocol)和SFTP(Secure File Transfer Protocol)等。每种协议都有其特定的优势和应用场景,我们可以根据具体需求来选择适合的协议进行文件传输。 ### 回答2: HTTP文件上传下载是指通过HTTP协议实现文件的传输和下载。在HTTP协议中,文件上传和下载是通过HTTP的POST和GET请求方法进行的。 文件上传:通过HTTP的POST请求方法,将文件的内容和相关信息作为请求的主体部分发送到服务器。通常情况下,需要在请求头中指定Content-Type为multipart/form-data,以表明请求主体中包含了二进制的文件数据。文件上传可以使用表单的形式,通过<input type="file">元素进行选择,也可以使用编程语言提供的相关API进行实现。一般来说,文件上传需要在服务器端进行相应处理,将接收到的文件保存到指定位置。 文件下载:通过HTTP的GET请求方法,客户端向服务器请求一个文件。服务器端根据请求的URL定位到相应的文件,并将文件内容作为响应的主体返回给客户端。在响应头中,可以设置Content-Disposition字段来指定文件的名称和下载方式,例如Content-Disposition: attachment; filename="example.txt",表示以附件的方式下载名为example.txt的文件。客户端接收到响应后,可以将文件保存到本地位置。 总结来说,HTTP文件上传下载是通过POST和GET请求方法实现的。文件上传通过POST请求将文件及相关信息发送到服务器,而文件下载则是通过GET请求从服务器获取文件并返回给客户端。 ### 回答3: HTTP文件上传下载是指通过HTTP协议进行文件的上传和下载操作。在Web开发中,常常需要用户上传文件或者提供文件供用户下载,这就需要利用HTTP协议来实现文件的传输。 在文件上传时,客户端通过HTTP POST请求将文件发送给服务器。在请求头中设置Content-Type为multipart/form-data,同时将文件作为请求体的一部分发送给服务器。服务器接收到文件后,可以进行一些处理,例如保存到指定的位置或者进行其他操作。 在文件下载时,客户端发送一个HTTP GET请求给服务器,服务器将文件以指定的格式和方式返回给客户端。客户端接收到服务器返回的文件后,可以选择直接保存到本地或者进行其他处理,例如显示在浏览器中或者进行进一步操作。 在HTTP文件上传下载中,需要注意以下几点: 1. 文件大小限制:由于文件可能较大,所以需要进行大小限制,避免影响服务器性能和用户体验。 2. 文件类型限制:对于上传的文件,需要进行类型限制,避免上传危险文件或者无法处理的文件。 3. 文件存储位置:服务器需要设定合适的存储位置,将上传的文件保存到指定目录中,同时需要管理文件的命名和存储结构。 4. 文件传输进度显示:在上传或下载大文件时,可以实现文件传输进度的显示,增强用户体验。 5. 安全性考虑:对于上传的文件,需要进行安全性检查,避免上传恶意文件导致服务器的安全风险。 总之,HTTP文件上传下载是在Web开发中常见的功能,通过使用HTTP协议进行文件的传输,可以方便地实现用户上传和下载文件的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值