文件上传原理:Web上传文件的原理及实现

现在有很多Web程序都有上传功能,实现上传功能的组件或框架也很多,如基于java的Commons
FileUpload、还有Struts1.x和Struts2中带的上传文件功能(实际上,Struts2在底层也使用了Commons
FileUpload)。在asp.net中也有相应的上传文件的控件。 
 
  虽然现在有很多上传组件可以利用,但是了解Web上传文件的原理,对于处理突然出现的问题会有很大的
帮助,下面就来讲一下通过浏览器上传文件的基本原理。在了解了原理之后,就可以非常容易地自制满足自身
需要的上传组件了。 
 
  众所周知,在客户端代码中需要使用<input type='file' name='file' />来选择要上传的文件,并上传
,代码如上: 
 
<html> 
    <head> 
        <title>upload</title> 
        <meta http-equiv="description" content="this is my page"> 
        <meta http-equiv="content-type" content="text/html;  charset=GB18030"> 
    </head> 
 
    <body> 
        <form action="servlet/UploadFile" method="post" 
            enctype="multipart/form-data"> 
            <input type="file" name="file1" id="file1" /> 
            <input type="file" name="file2" id="file2" /> 
            <input type="submit" value="上传" /> 
        </form> 
    </body> 
</html> 
 
 
  从上面的代码可以看出,有两个文件选择框(file1和file2),在上传文件时,<form>标签必须加上
enctype="multipart/form-data",否则浏览器无法将文件内容上传到服务端。下面我们来做个实验。在
Servlet的doPost方法中编写如下的代码,如果想使用asp.net或其他的语言或技术,也可以很容易实现相应的
功能。  
    public void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException 
    { 
        java.io.InputStream is = request.getInputStream();  
        java.io.FileOutputStream fos = new java.io.FileOutputStream("d:\\out.txt");  
         
        byte[] buffer = new byte[8192];  
        int count = 0;  
        while((count = is.read(buffer)) >0) 
        { 
            fos.write(buffer, 0, count);  
        }         
        fos.close();  
    } 
 
    上面的功能非常简单,只是通过request获得一个InputStream对象,并通过这个对象从客户端获得发送过
来的字节流(注意,一定要用字节流,因为,上传的文件可能是二进制文件,如图象文件,因此,使用字节流
会更通用)。并将这些字节流保存在D盘的out.txt文件中。然后我们打开out.txt,文件的内容如图1所示: 
 
 
图1 
 
    由于out.txt是使用文本形式打开的,并且file1上传的是a.jpg(一个图象文件),因此,显示的是一些乱码。我
们可以不用管它们。只需要看看这些内容的头部。我们很快就可以找到规律。每一个文件内容的头部都由“---
--------------------------30514443229777”分隔,然后是这个文件的属性,如下: 
 
Content-Disposition: form-data;  name="file1";  filename="a.jpg" 
 
Content-Type: image/jpeg 
 
  其中包含了文件选择框的name属性,还有上传的文件名(filename字段),要注意的,firefox在上传时
,这个filename属性值只是文件名,如果使用IE,就是带路径的文件名,如D:"a.jpg。 
 
  接下来的规则就和HTTP的头一样了,以一个空行("r"n)分隔。后面就是文件的具体内容。现在最关键的
文件的结尾,从图1可以看出,文件的结尾也是“-----------------------------30514443229777”,因此,可以断定,第一个上传的文件(包括文件头)是夹在两个“-----------------------------30514443229777”之
间的。而“-----------------------------30514443229777”就是multipart/form-data协议的分隔符。但这里
还有一个最关键的问题。这个分隔符每次上传都不一样,服务端是如何知道每次上传的这个分隔符的呢? 
 
  实际上,这个分隔符是通过HTTP请求头的Content-Type字段获得,可通过下面的代码输出这个字段值: 
 
System.out.println(request.getHeader("Content-type"));  
 
  输出的内容如下: 
 
multipart/form-data;  boundary=---------------------------106712230227687 
 
  只要在服务端获得boundary后面的值即可。经过测试,Content-Type中的分隔符号中的“-”比实际上传
的“-”少两个,不知是怎么回事。不过这没关系,我们可以认为每一个文件块是以""r"n—“结尾的,或是直
接将从boundary获得的分隔符加两个“—”。而最后结尾的分隔符是“---------------------------
106712230227687—”,后面多了两个“—”。 
 
  综合上述,也就是说,一个文件块是以“---------------------------106712230227687”开头,以
“—”结尾,从图2可以看出这一切。 
 
 
图2  
 
    至于剩下的工作,就是按着上面的规则来分析这些字符流了。分析的方法很多。在这里就不详述了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值