关于http上传文件(转)

1、概述
在最初的 http 协议中,没有上传文件方面的功能。 rfc1867 ( http://www.ietf.org/rfc/rfc1867.txt ) 为 http 协议添加了这个功能。客户端的浏览器,如 Microsoft IE, Mozila, Opera 等,按照此规范将用户指定的文件发送到服务器。服务器端的网页程序,如 php, asp, jsp 等,可以按照此规范,解析出用户发送来的文件。
Microsoft IE, Mozila, Opera 已经支持此协议,在网页中使用一个特殊的 form 就可以发送文件。
绝大部分 http server ,包括 tomcat ,已经支持此协议,可接受发送来的文件。
各种网页程序,如 php, asp, jsp 中,对于上传文件已经做了很好的封装。
2、上传文件的实例:用 servelet 实现(http server 为 tomcat 4.1.24)
1. 在一个 html 网页中,写一个如下的form :
<form enctype="multipart/form-data" action="http://192.168.29.65/UploadFile" method=post>
    load multi files :<br>
    <input name="userfile1" type="file"><br>
    <input name="userfile2" type="file"><br>
    <input name="userfile3" type="file"><br>
    <input name="userfile4" type="file"><br>
    text field :<input type="text" name="text" value="text"><br>
    <input type="submit" value="提交"><input type=reset>
</form>
2. 服务端 servelet 的编写
现在第三方的 http upload file 工具库很多。Jarkata 项目本身就提供了fileupload 包http://jakarta.apache.org/commons/fileupload/ 。文件上传、表单项处理、效率问题基本上都考虑到了。在 struts 中就使用了这个包,不过是用 struts 的方式另行封装了一次。这里我们直接使用 fileupload 包。至于struts 中的用法,请参阅 struts 相关文档。
这个处理文件上传的 servelet 主要代码如下:
public void doPost( HttpServletRequest request, HttpServletResponse response ) {
    DiskFileUpload diskFileUpload = new DiskFileUpload();
    // 允许文件最大长度
    diskFileUpload.setSizeMax( 100*1024*1024 );
    // 设置内存缓冲大小
    diskFileUpload.setSizeThreshold( 4096 );
    // 设置临时目录
    diskFileUpload.setRepositoryPath( "c:/tmp" );
    List fileItems = diskFileUpload.parseRequest( request );
    Iterator iter = fileItems.iterator();
    for( ; iter.hasNext(); ) {
        FileItem fileItem = (FileItem) iter.next();
        if( fileItem.isFormField() ) {
            // 当前是一个表单项
            out.println( "form field : " + fileItem.getFieldName() + ", " + fileItem.getString() );
        } else {
            // 当前是一个上传的文件
            String fileName = fileItem.getName();
            fileItem.write( new File("c:/uploads/"+fileName) );
        }
    }
}
为简略起见,异常处理,文件重命名等细节没有写出。
3、 客户端发送内容构造
假设接受文件的网页程序位于 http://192.168.29.65/upload_file/UploadFile.
假设我们要发送一个二进制文件、一个文本框表单项、一个密码框表单项。文件名为 E:\s ,其内容如下:(其中的XXX代表二进制数据,如 01 02 03)
a
bb
XXX
ccc
客户端应该向 192.168.29.65 发送如下内容:
POST /upload_file/UploadFile HTTP/1.1
Accept: text/plain, */*
Accept-Language: zh-cn
Host: 192.168.29.65:80
Content-Type:multipart/form-data;boundary=---------------------------7d33a816d302b6
User-Agent: Mozilla/4.0 (compatible; OpenOffice.org)
Content-Length: 424
Connection: Keep-Alive
-----------------------------7d33a816d302b6
Content-Disposition: form-data; name="userfile1"; filename="E:\s"
Content-Type: application/octet-stream
a
bb
XXX
ccc
-----------------------------7d33a816d302b6
Content-Disposition: form-data; name="text1"
foo
-----------------------------7d33a816d302b6
Content-Disposition: form-data; name="password1"
bar
-----------------------------7d33a816d302b6--
此内容必须一字不差,包括最后的回车。
注意:Content-Length: 424 这里的424是红色内容的总长度(包括最后的回车)
注意这一行:
Content-Type: multipart/form-data; boundary=---------------------------7d33a816d302b6
根据 rfc1867, multipart/form-data是必须的.
---------------------------7d33a816d302b6 是分隔符,分隔多个文件、表单项。其中33a816d302b6 是即时生成的一个数字,用以确保整个分隔符不会在文件或表单项的内容中出现。前面的 ---------------------------7d 是 IE 特有的标志。 Mozila 为---------------------------71
用手工发送这个例子,在上述的 servlet 中检验通过。
(上面有一个回车)用户可以选择多个文件,填写表单其它项,点击“提交”按钮后就开始上传给 http://192.168.29.65/upload_file/UploadFile 这是一个 servelet 程序
注意 enctype="multipart/form-data", method=post, type="file" 。根据 rfc1867, 这三个属性是必须的。multipart/form-data 是新增的编码类型,以提高二进制文件的传输效率。具体的解释请参阅 rfc1867

------------------------------------------------------- boundary的理解:------------------------------

RFC1867协议
在原有的基础上添加了对file域的支持,同时限定了form的method必须为POST,enctype必须为multipart/form-data.
实际上enctype最后会转换成Content-Type。

为了方便查看我们写一个页面,然后使用firefox的firebug插件查看network信息和google chrome的debug功能。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>啊啊啊</title>
</head>
<body>
ads高
<form action="http://127.0.0.1:8080/daowole/rb1" method="post" enctype="multipart/form-data"><input
name="body" value="123" /> <input name="name"  type="file" /><input
type="submit" /></form>
</body>
</html>

提交后首先查看头信息(Request headers)
firefox将headers和content分隔开了,卡起来不清晰,我就看google了。
Accept:application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Charset:GBK,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:zh-CN,zh;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:140952
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryuwYcfA2AIgxqIxA0
Host:127.0.0.1:8081
Origin:null
User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.151 Safari/534.16
首先是Content-Type
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryuwYcfA2AIgxqIxA0
首先指定了表单类型为multipart/form-data;。
boundary是分隔符
因为上传文件不在使用原有的http协议了。请求内容不再可能以
x = y方式发送了。而使用了
分隔符
字段内容
分隔符号
字段内容2
而boundary就是指定分隔符号的标志。
请求的内容就应该是这样的了。

------WebKitFormBoundaryuwYcfA2AIgxqIxA0
Content-Disposition: form-data; name="body"

123
------WebKitFormBoundaryuwYcfA2AIgxqIxA0
Content-Disposition: form-data; name="name"; filename="QQ.exe"
Content-Type: application/x-msdownload
文件本身的字节

 

--------------------------------------事实上这才是http能上传文件的源头-------------------

rfc1867:


目录
1.摘要    2
2.带有文件提交功能的HTML表单    2
3.建议采纳的应用    3
3.1 FILE组件的显示    4
3.2提交之后的动作    4
3.3 multipart/form-data的使用    4
3.4其他属性的解释    5
4.向后兼容性的考虑    5
5.其他的考虑    6
5.1压缩,加密    6
5.2文件传输延迟    6
5.3传输二进制数据的其他解决办法    7
5.4 不修改<INPUT>    7
5.5字段内容的默认类型    8
5.6允许ACTION指向"mailto:"    8
5.7第三方传输的远程文件    8
5.8用ENCTYPE=x-www-form-urlencoded来传输文件    8
5.9将CRLF作为行分隔符    8
5.10和multipart/related的关系    9
5.11含有非ASCII码的字段名    9
6.例子    9
7. multipart/form-data的登记    10
8.安全性考虑    11
9.结论    11
作者地址:    12
A.为multipart/form-data登记的媒体类型    12
参考:    13

1.摘要

目前,HTML的表单让表单编写者能够通过表单得到浏览表单的用户的信息。在许多需要得
到用户输入的应用中,表单被证明是非常有用的。但是,因为HTML表单并没有提供让用
户可以上传文件或数据的途径,这种能力受到了一定的限制。所以那些需要从用户那儿得到
文件的服务提供商们不得不自己来建立相应的应用程序。(我们可以在www-talk邮件列表
中找到这类客户浏览器的例子。)既然文件上传是能够让许多应用程序受益的特点,这使得
人们要求扩展HTML,以便能让信息提供商们能够统一地处理文件上传请求,并为文件上传
响应提供统一的MIME兼容的表现形式。本方案同时也包括了一个向后保持兼容的策略介
绍,以便能让新的服务器能和现有的HTML客户端进行互动。

本建议独立于现有的各版本HTML。

2.带有文件提交功能的HTML表单

现有的HTML规范为INPUT元素的TYPE属性定义了八种可能的值,分别是:CHECKBOX,
HIDDEN, IMAGE, PASSWORD, RADIO, RESET, SUBMIT, TEXT. 另外,当表单采用
POST方式的时候,表单默认的具有"application/x-www-form-urlencoded" 的ENCTYPE
属性。

本建议对HTML做出了两处修改:
1)为INPUT元素的TYPE属性增加了一个FILE选项。
2)INPUT标记可以具有ACCEPT属性,该属性能够指定可被上传的文件类型或文件格式
列表。

另外,本建议还定义了一种新的MIME类型:multipart/form-data,以及当处理一个带有
ENCTYPE="multipart/form-data" 并且/或含有<INPUT type="file">的标记的表单时所应该
采取的行为。

这些改变可以被视为是完全独立的,但对于合理的文件上传需求来说,这些改变都是必需的。

举例来说,当HTML表单作者想让用户能够上传一个或更多的文件时,他可以这么写:

    <FORM ENCTYPE="multipart/form-data" ACTION="_URL_" METHOD=POST>

    File to process: <INPUT NAME="userfile1" TYPE="file">

    <INPUT TYPE="submit" VALUE="Send File">

    </FORM>

HTML DTD里所需要做出的改动是为InputType实体增加一个选项。此外,我们也建议用
一系列用逗号分隔的文件类型来作为INPUT标记的ACCEPT属性。

  ... (其他元素) ...

  <!ENTITY % InputType "(TEXT | PASSWORD | CHECKBOX |
                         RADIO | SUBMIT | RESET |
                         IMAGE | HIDDEN | FILE )">
  <!ELEMENT INPUT - 0 EMPTY>
  <!ATTLIST INPUT
          TYPE %InputType TEXT
          NAME CDATA #IMPLIED  -- required for all but submit and reset
          VALUE CDATA #IMPLIED
          SRC %URI #IMPLIED  -- for image inputs --
          CHECKED (CHECKED) #IMPLIED
          SIZE CDATA #IMPLIED  --like NUMBERS,
                                  but delimited with comma, not space
          MAXLENGTH NUMBER #IMPLIED
          ALIGN (top|middle|bottom) #IMPLIED
          ACCEPT CDATA #IMPLIED --list of content types
          >

  ... (其他元素) ...

3.建议采纳的应用

因为用户端有多种途径来选择最合适的方式来解释HTML内容,本节针对其中的一种:
WWW浏览器来建议如何实现文件上传。

3.1 FILE组件的显示

当浏览器遇到一个FILE类型的INPUT标记时,它将显示一个文件名(或者是前面所选择
的文件名),和一个Browse(浏览)按钮或类似的选择方式。选择这个Browse(浏览)
按钮将触发浏览器对应于其所运行的平台相应的文件选择方式。举例来说,基于Windows
的浏览器将会弹出一个文件选择窗口。在这个文件选择窗口中,用户可以进行替换现有的选
择,为选择增加一个新的文件等操作。浏览器的设计者可以自己确定所选择的文件名列表是
否可以被用户手工修改。

如果该标记有ACCEPT属性,浏览器还可以限制符合该平台的文件类型。

3.2提交之后的动作

当用户填完了表单,并且选择了SUBMIT元素,浏览器应该将表单的内容和所选择的文件
的内容传回。对于传送那些大容量的二进制数据或包含非ASCII字符的文本来说,
application/x-www-form-urlencoded编码类型是远远不能满足要求的。于是,我们提出了一
种新的媒体类型:multipart/form-data,用来作为将填写好的表单内容从客户端传回到主机
端的高效方式。

3.3 multipart/form-data的使用

第7节里面对multipart/form-data做出了具体的定义。最极端的情况是选择中不包括任何数
据。(这种选择在某些情况下是非常可能的。)作为数据流的一部分,表单中的每一项内容
都按照它们在表单中出现的顺序被依次发送。每一部分由它们在HTML表单中INPUT标记
的名字所标识。如果该部分内容的类型是已知的,就用相应的媒体内容进行标识(举例来说,
可以从文件的扩展名或者从操作系统的相关类型信息中得知),否则的话,就标识为
application/octet-stream。

如果有多个文件被选中上传,它们必须按照multipart/mixed格式进行传输。

虽然HTTP协议能够传送任意形式的二进制数据,邮件传送(举例来说,如果表单的ACTION
是mailto的形式)的默认方式是7位编码。但是如果传送的内容和默认的编码方式不兼容
的话,所传送的内容将需要进行编码,并且加上一个"content-transfer-encoding"标识头。
(此方面详细内容可参看RFC 1521第5节)。

上传文件的原始文件名也应该一道被传送,或者是作为filename参数,或者是
'content-disposition: form-data'的标题头,如果传送的是多个文件的话,也可以是子内容中
的'content-disposition:file'的标题头。客户端应用程序应该尽量提供文件名。如果客户端操
作系统上的文件名包含有非US-ASCII字符,文件名可以用类似的字符或者是按照RFC1522
中描述的方法进行编码。这在某些情况下有其便利之处,比如说上传的文件中可能包含互相
关联的关系,例如一个TeX文件可能会有一个后缀为.sty的附加类型描述文件。

在服务器端,ACTION可能是指向一个HTTP地址,借助CGI来完成表单的处理程序。在
这种情况下,CGI程序将会注意到内容类型是multipart/form-data,并采取措施来处理不同
的字段(校验合法性,按照处理顺序将文件写入磁盘等等)

3.4其他属性的解释

<INPUT TYPE=file>标记可以有一个VALUE属性来指定默认的文件名。这有可能会影响到
平台无关性,但也可能非常有用。举例来说在某些有多个提交过程的操作中,可以避免让用
户不停的选择同样的文件名。

可以用“SIZE=宽,高”来指定SIZE属性。宽度默认为文件名的宽度,而高度是所选择的
文件列表的显示区域大小。举例来说,对那些希望在浏览器中实现上传多个文件,并且显示
多行的文件输入框(当然,旁边还有一个Browse按钮)的人来说,这点非常有用。当没有
指定高度值时,将只会显示一个单行的文件输入框(如果表单设计者只希望上传一个文件的
话),而如果高度值大于1的话,将显示带有滚动条的多行输入框(如果表单设计者希望
上传多个文件的话)。

4.向后兼容性的考虑

尽管对于现有的WWW表单机制来说,一个成功的改进方案不一定要考虑这点,但是考虑
一种迁移的策略也是有帮助的:对于那些使用比较老版本的浏览器的用户来说,借助于一个
附加程序,他们也能够进行文件上传。现有的绝大部分浏览器在碰到<INPUT TYPE=FILE>
时,会将它按照<INPUT TYPE=TEXT>对待,并给用户一个文本输入框。用户能在这个框
里面输入文件名。此外,似乎现有的浏览器都忽略了表单元素中的ENCTYPE参数,并按
照application/x-www-form-urlencoded传送表单数据。

这样的话,当服务器端的CGI处理传送回来的表单数据时,如果数据类型是
application/x-www-form-urlencoded,而不是multipart/form-data,就可以知道用户使用的
浏览器没有实现文件上传。

在这种情况下,服务器端的CGI不会返回一个“text/html”响应,而是返回一个数据流以
便附加程序能够处理;这个数据流可能被标识为"application/x-please-send-files",并包含
以下内容:

?    表单数据实际需要被传送至的(标准)URL地址(以CRLF结尾)
?    应该包含文件内容的字段名字列表(用空格间隔开,以CRLF结尾)
?    客户端传至服务器端的application/x-www-form-urlencoded表单数据

这时候,浏览器需要被设置以便能启动一个附加程序来处理application/x-please-send-files
请求。

附加程序能够处理表单数据,并且注意到那些包含有“本地文件名”、需要用实际的文件内
容替代的字段。它可能会需要提示用户来改变或增加文件列表,然后重新将数据和文件内容
打包成multipart/form-data,并再次传回给服务器。

附加程序能够象那些新版本的浏览器实际处理数据那样处理表单,并按照原始的ACTION
指定的URL地址将数据发送。这样处理的好处是服务器端可以使用“同样的”CGI来处理
老版本及新版本的浏览器。

附加程序不需要显示表单数据,但是“需要”确保用户能够得知传送的文件是恰当的。(这
是为了避免那些不怀好意的服务器要求传送用户本来没有要求传送的文件而可能带来的安
全问题。)如果能够显示当前正在传送的文件状态,将非常有帮助。

5.其他的考虑

5.1压缩,加密

本方案并没有考虑可能存在的文件压缩。经过一定的考虑,我们发现如果要让浏览器自己来
决定那些文件需要被压缩的话,对文件压缩进行优化的讨论将变得非常复杂。许多连接层的
传输协议(比如说高速调制解调器)在连接层对数据进行压缩,如果在这一层上对压缩进行
优化可能不是非常恰当。如果确实希望如此的话,可以让浏览器选择是否对文件内容进行
content-transfer-encoding的x-compress压缩,并且在服务器端处理数据前进行数据解压
缩。但这将不在该方案中进行讨论。

同样,本方案也没有包括对数据进行加密的机制。这应该由其他的数据保密传输协议进行处
理,或者是保密HTTP(HTTPs),或者是电子邮件。

5.2文件传输延迟

在某些情况下,在确实准备接受数据前,服务器先对表单数据中的某些元素(比如说用户名,
账号等)进行验证是推荐的做法。但是,经过一定的考虑后,我们认为如果服务器想这样做
的话,最好是采用一系列的表单,并将前面所验证过的数据元素作为“隐藏”字段传回给客
户端,或者是通过安排表单使那些需要验证的元素先显示出来。这样的话,那些需要做复杂
的应用的服务器可以自己维持事务处理的状态,而那些简单的应用的则可以实现得简单些。

HTTP协议可能需要知道整个事务处理中的内容总长度。即使没有明确要求,HTTP客户端
也应该提供上传的所有文件的内容总长度,这样一个繁忙的服务器就能够判断文件的内容是
否是过大以至于将不能完整地处理,从而返回一个错误代码并关闭该连接,而不用等到接受
了所有的数据才进行判断。目前一些现有的CGI应用对所有的POST事务都需要知道内容
总长度。

如果INPUT标记含有一个MAXLENGTH属性,客户端可以将这个属性值看作是服务器端
所能够接受的传送文件的最大字节数。在这种情况下,服务器能够在上传开始前,提示客户
端在服务器上有多少空间可以用来进行文件上传。但是应该引起注意的是,这仅仅是一个提
示,在表单被创建后和文件上传前,服务器的实际需求可能会发生改变。

在任何情况下,如果接受的文件过大的话,任何一个HTTP服务器都有可能在文件传输的
过程中中断传输。

5.3传输二进制数据的其他解决办法

有些人曾经建议使用一种新的MIME类型"aggregate",比如说aggregate/mixed 或是
content-transfer-encoding "包"来描述那些不确定长度的二进制数据,而不是靠分解为多个
部分来表示。虽然我们并不反对这么做,但这需要增加额外的设计和标准化工作来让大家接
受并理解"aggregate"。 从另一方面来说,"分解为多部分"的机制工作得很好,能够非常简
单的在客户发送端和服务器接受端加以实现,而且能像其他一些综合处理二进制数据的方式
一样高效率地工作。

5.4 不修改<INPUT>

有些人曾经提到过,为什么要修改INPUT来实现文件上传功能,而不是为表单元素提供一
个完全不同的类型?在这种种考虑中,当我们使用<INPUT>时,最重要的考虑是兼容策略。
事实上,<INPUT>标记"早就已经"被修改过以用来包含各种输入的数据,相比较于创造不同
种类的<INPUT>标记,对<INPUT>进行加强看起来是更为合理的办法。INPUT的“类型”
并不是它所返回的内容类型,而更象是“多类型”的,也就是说,它表示了和用户互动的方
式。它的定义被仔细地斟酌以便其既能在文本浏览器,也能在声音标记中使用。

5.5字段内容的默认类型

HTML中许多字段都需要用户进行输入。过去人们对这些表单数据应该如何传回到服务器有
些意见分歧。但是将这些INPUT字段的内容看成是纯文本很明显将有助于消除这方面的分
歧。客户端再将这些数据传回到服务器以前应该将它们用CRLF分隔开,并进行适当的编
码。

5.6允许ACTION指向"mailto:"

虽然和本方案无关,但是如果允许客户端的表单的ACTION指向一个"mailto:"地址将肯定非
常有用。不管本方案本身怎么设想,这都是一个好主意。同样的,那些用来接受邮件的表单
的ACTION也应该默认指向"reply-to:"。这两个设想有助于让HTML表单借助于HTTP服务
器工作,但通过电子邮件发送内容。或者也可以这么做:允许HTML表单能够被电子邮件
发送,当HTML中指明的邮件收件人填写完表单后,再将结果发送作为邮件传送回来。

5.7第三方传输的远程文件
在某些情况下,那些操作客户端软件的用户可能希望通过指定一个URL地址来传送位于网
上,而不是本地的数据文件。在这种情况下,浏览器能够发送给客户一个指向远程数据的连
接,而不是实际的所有内容吗?这种要求实际上是可以办得到的,举例来说,只要让客户在
发送给服务器的数据当中,用"message/external-body"来指明数据的类型,同时将
"access-type"设置为连接的地址,并在发送的内容中包含远程数据的URL地址就可以了。

5.8用ENCTYPE=x-www-form-urlencoded来传输文件

如果一个表单包含了<INPUT TYPE=file>元素,但是表单本身未包含ENCTYPE属性,也
就是没有详细说明相应的行为的话。这将可能导致为服务器进行不恰当的对大量数据进行
URN编码,而这将是服务器端所不希望看到的

5.9将CRLF作为行分隔符

象所有的MIME传输一样,在用POST方式传送表单内容的时候,CRLF都被用作行的分
隔符。

5.10和multipart/related的关系
MIMESGML小组正在考虑制订一种新的类型,称为multipart/related。它包含和
multipart/form-data类似的特点。Form-data的使用和应用却是完全不同的,所以它被单独
进行描述。

在某些情况下,有可能将HTML表单的内容(包括文件)作为multipart/related进行编码,
但这和本方案所讨论的情况有很大的不同。

5.11含有非ASCII码的字段名

需要注意的是MIME的标题头通常是由7位的US-ASCII字符集构成。所以如果字段名的字
符不属于该字符集的话,就必须按照RFC 1522里面所提到的方法进行编码。在HTML 2.0
里面,默认的字符集是ISO-8859-1,而由非ASCII码字符组成的字段名就必须进行编码。

6.例子

假设服务器段提供的是如下的HTML:

     <FORM ACTION="http://server.dom/cgi/handle"
           ENCTYPE="multipart/form-data"
           METHOD=POST>
     What is your name? <INPUT TYPE=TEXT NAME=submitter>
     What files are you sending? <INPUT TYPE=FILE NAME=pics>
     </FORM>

用户在“姓名”字段里面填写"Joe Blow",对问题'What files are you sending?',用户选择
了一个文本文件"file1.txt"。

客户段可能发送回如下的数据:

        Content-type: multipart/form-data, boundary=AaB03x

        --AaB03x
        content-disposition: form-data; name="field1"

        Joe Blow
        --AaB03x
        content-disposition: form-data; name="pics"; filename="file1.txt"
        Content-Type: text/plain

         ... file1.txt 的内容...
        --AaB03x--

如果用户同时还选择了另一个图片文件"file2.gif",那么客户端可能发送的数据将是:

        Content-type: multipart/form-data, boundary=AaB03x

        --AaB03x
        content-disposition: form-data; name="field1"

        Joe Blow
        --AaB03x
        content-disposition: form-data; name="pics"
        Content-type: multipart/mixed, boundary=BbC04y

        --BbC04y
        Content-disposition: attachment; filename="file1.txt"

        Content-Type: text/plain

        ... file1.txt 的内容...
        --BbC04y
        Content-disposition: attachment; filename="file2.gif"
        Content-type: image/gif
        Content-Transfer-Encoding: binary

          ... file2.gif的内容...
        --BbC04y--
        --AaB03x--

7. multipart/form-data的登记
multipart/form-data的媒体内容遵从RFC 1521所规定的多部分的数据流规则。它主要被用
来描述表单填写后返回的数据。在一个表单中(这里指的是HTML,当然其他一些应用也可
能使用表单),有一系列字段提供给用户进行填写,每个字段都有自己的名字。在一个确定
的表单中,每个名字都是唯一的。

multipart/form-data由多个部分组成,每一部分都有一个content-disposition标题头,它的
值是"form-data",它的属性指明了其在表单内的字段名。举例来说,'content-disposition:
form-data; name="xxxxx"',这里的xxxxx就是对应于该字段的字段名。如果字段名包含非
ASCII码字符的话,还应该按照RFC 1522里面所规定的方法进行编码。

对所有的多部分MIME类型来说,每一部分有一个可选的Content-Type,默认的值是
text/plain。如果文件的内容是通过表单填写上传返回的话,那么输入的文件就被定义为
application/octet-stream,或者,如果知道是什么类型的话,就定义为相应的媒体类型。如
果一个表单返回多个文件,那么它们就作为multipart/form-data中所结合的multipart/mixed
被返回。

如果所传送的内容不符合默认的编码方式的话,该部分都将被编码,并加上
"content-transfer-encoding"的标题头。

上传的文件也可能被指定文件名,文件名可以由标题头"content-disposition"中的filename
参数所指定。虽然这并不是必需的,但我们强烈建议在能够得知原始文件名的情况下这么做。
对于很多应用程序来说,这都是必需的或者是有用的。

8.安全性考虑

如果用户没有明确要求发送某个文件,用户端就不应该发送该文件,这点非常重要。所以,
在碰到<INPUT TYPE=file VALUE="yyyy">的标记的时候,HTML解释器应该能够让用户确
认默认的文件名。不要使用隐含的字段来指定任何文件。

本方案并没有包括对数据加密的讨论;这应该是保密数据传输协议,或者是加密HTTP,或
者是MOSS所提供的加密协议(在RFC 1848中有具体的描述)所讨论的问题。

一旦文件上传成功,就将取决于文件接受方来处理文件或者是储存在适当的地方。

9.结论

我们所建议的应用让客户端有很大的弹性来决定它发送到服务器的文件的类型和数量,也让
服务器端有权决定是否接受上传的文件,同时也让服务器有机会和那些不支持类型为file的
INPUT的浏览器进行互动。

对HTML DTD的改动虽然很简单,但却有很大的作用。能够让目前这种缺少文件上传机制
的万维网实现很多种服务。这将给万维网实际的性能增加许多惊人的价值。

posted on   每当变幻时  阅读(2071)  评论(0编辑  收藏  举报

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述

导航

< 2013年4月 >
31 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 1 2 3 4
5 6 7 8 9 10 11

统计

点击右上角即可分享
微信分享提示