网页表单是一个web基础设施,提供了交互接口,作为使用web技术的开发人员,了解其工作原理,是必须的功课,本文描述表单域和二进制数据一同传输并被处理.
有关表单资料,若需要可参考http://www.htmlhelp.com/reference/html40/forms/form.html.
在表单元素中 enctype 属性指定了传递给服务器的表单数据集编码的内容类型,它的默认值是“application/x-www-form-urlencoded”,用于通常的数据提交格式,enctype 属性有三个值: application/x-www-form-urlencoded, multipart/form-data, text/plain, 它们都属于MIME类型,关于该类型可参考http://www.ietf.org/rfc/rfc2045.txt .
上传二进制数据时需要multipart/form-data, 并必须把表单属性method设为post, ACCEPT-CHARSET属性是表单处理器能够处理的编码字符集,若没有指定该属性,表单默认是UNKNOWN,可根据需要指定为iso-8859-1 utf-8,关于已经认可的标准字符集,可参考http://www.iana.org/assignments/character-sets.
基于java的jsp演示一个上载过程,并把上载的数据向用户直接返回.其代码为:
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="java.util.*" %>
<form name="frm" enctype="multipart/form-data" method="post" action="param1.jsp">
<input type="text" name="test" value="测试"><br>
<input type="file" name="image" value="this is a image"><br>
<input type="submit" name="sub" value="upload">
</form>
</body>
</html>
在表单中没有指定ACCEPT-CHARSET属性,在使用us-ascii编码时,表单域被处理为gb2312编码, multipart/form-data类型使用7-bit US-ASCII编码表单数据.
param1.jsp代码为:
<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="java.util.*" %>
<%@ page import="org.common.servlet.*" %>
<html>
<body>
<%
ServletOutputStream sos=response.getOutputStream();
int length= Integer.parseInt(request.getHeader("Content-Length"));
String contenttype=request.getContentType();
String enc=request.getCharacterEncoding();
response.setContentType(contenttype);
ServletInputStream sis= request.getInputStream();
int count=0;
byte[] b=new byte[2048];
while((count=sis.read(b))!=-1){
sos.write(b,0,count);
}
sos.flush();
%>
</body>
<html>
首先该代码会报告错误: getOutputStream调用已经由getWriter执行了.不过程序仍然可以运行,在真正的应用中,把它写成servlet.就可解决.出现这个问题原因是serlvet规范指出在request上调用getOutputStream和getWriter必须是二选一.
弹出对话框后问你是否打开或者是保存,点保存,然后打开结果你会看到:
-----------------------------7d52e 1f 4065c
Content-Disposition: form-data; name="test"
简化
-----------------------------7d52e 1f 4065c
Content-Disposition: form-data; name="file1"
三季稻看法上
-----------------------------7d52e 1f 4065c
Content-Disposition: form-data; name="image"; filename=""
Content-Type: application/octet-stream
-----------------------------7d52e 1f 4065c
Content-Disposition: form-data; name="sub"
upload
-----------------------------7d52e 1f 4065c—
当你看到这个格式文件后,应该就理解了原来文件上传的原理就这么简单.
格式规定:每一行都是以回车换行(0xd0xa 1310)界定,每一个数据实体都以类似于-----------------------------7d52e1f4065c界定,最后的用户数据终止是以实体界定符号后加了两个连字符(--).
该格式一目了然, 实体界定符之间是表单域实体,该实体的name指定的串就是表单ui组件的name.其值是 回车换行+ui组件的值.
二进制数据实体多出了filename和Content-Type以便处理.
以上格式是遵守 http://www.ietf.org/rfc/rfc1867.txt 规范的,根据这个格式,我们可以编写自己的分析器来处理上传过来的数据.
通过这个具体实例,可加深对通信程序设计的理解.尤其是通信中控制数据和用户数据的设计和处理上.
参考资料:
http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type
http://www.faqs.org/docs/htmltut/forms/index.html
http://www.htmlhelp.com/reference/html40/forms/form.html
multipart/form-data 参考 http://www.faqs.org/rfcs/rfc2388.html