博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Web上传文件的原理及实现
阅读量:6306 次
发布时间:2019-06-22

本文共 2900 字,大约阅读时间需要 9 分钟。

现在有很多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
    
至于剩下的工作,就是按着上面的规则来分析这些字符流了。分析的方法很多。在这里就不详述了。
multipart/form-data
规 范原文:
Form-based File Upload in HTML:
 本文转自 androidguy 51CTO博客,原文链接:http://blog.51cto.com/androidguy/215335
,如需转载请自行联系原作者
你可能感兴趣的文章
接口和抽象类有什么区别
查看>>
Linux 下添加用户,修改权限
查看>>
请问view controller scene,该如何删除
查看>>
bootstrap新闻模块样式模板
查看>>
zzzzw_在线考试系统①准备篇
查看>>
App Store 审核被拒的23个理由
查看>>
剑指offer第二版-1.赋值运算符函数
查看>>
javascript 对象
查看>>
Android学习笔记——文件路径(/mnt/sdcard/...)、Uri(content://media/external/...)学习
查看>>
Echart:前端很好的数据图表展现工具+demo
查看>>
CATransform3D iOS动画特效详解
查看>>
Linux VNC黑屏(转)
查看>>
Java反射简介
查看>>
react脚手架应用以及iview安装
查看>>
shell学习之用户管理和文件属性
查看>>
day8--socket网络编程进阶
查看>>
node mysql模块写入中文字符时的乱码问题
查看>>
仍需"敬请期待"的微信沃卡
查看>>
分析Ajax爬取今日头条街拍美图
查看>>
内存分布简视图
查看>>