浏览器如何处理带上传控件的表单及服务器如何获取参数值

来源:互联网 发布:开一家小型咖啡屋 知乎 编辑:程序博客网 时间:2024/06/05 16:12
POST /servlet/testServlet HTTP/1.1
Host: localhost:8080
Cache-Control: no-cache
----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="image"; filename="jetty配置.png"
Content-Type: image/png
----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="comments"
截屏jetty配置

----WebKitFormBoundaryE19zNvXGzXaLvS5C

有文件上传时,表单提交方式必须是POST,且enctype必须是multipart/form-data

提交后,浏览器将表单的数据处理为一条消息,以控件为单元,用分隔符分开。

既可以上传键值对,也可以上传文件:

处理普通键值对控件的结果是一个请求头  Content-Disposition:form-data;name=属性名

                                            属性值

处理上传控件的结果是两个请求头        Content-Disposition:form-data;name=属性名;fileName=文件名称 

                                           Content-Type:上传文件的MIME类型

                                            文件流

1.get方式
get方式提交的话,表单项都保存在http header中,格式是
http://localhost:8080/hello.do?name1=value1&name2=value2这样的字符串。server端通过request.getParameter是可以取到值的。
2.post方式(enctype为缺省的application/x-www-form-urlencoded)
表单数据都保存在http的正文部分,格式类似于下面这样:用request.getParameter是可以取到数据的
name1=value1&name2=value2
3.post方式(enctype为multipart/form-data,多用于文件上传)
表单数据都保存在http的正文部分,各个表单项之间用分界线隔开,分界线格式类似于下面这样。这时用request.getParameter是取不到数据的,而是需要调用request.getInputStream()方法来取数据,不过取到的是个InputStream,所以无法直接获取指定的表单项(需要自己对取到的流进行解析,才能得到表单项以及上传的文件内容等信息)。这种需求属于比较共通的功能,所以有很多开源的组件可以直接利用。比如:apache的fileupload组件,smartupload等。通过这些开源的upload组件提供的API,就可以直接从request中取得指定的表单项了。
-----------------------------7d33a816d302b6
Content-Disposition:form-data;
name="userfile1";
filename="C:\my.txt"
Content-Type:application/octet-stream
abbXXXccc
-----------------------------7d33a816d302b6
Content-Disposition: form-data;
name="name1" value1
-----------------------------7d33a816d302b6
Content-Disposition: form-data;
name="name2" value2
-----------------------------7d33a816d302b6

protected void doPost(HttpServletRequest request, HttpServletResponse response) {response.setCharacterEncoding("utf-8");String fileDir = "";String serverFileName = "";String serverFilePath = "";PrintWriter writer = null;try {writer = response.getWriter();if (ServletFileUpload.isMultipartContent(request)) {DiskFileItemFactory factory = new DiskFileItemFactory(); // 基于磁盘文件项目创建一个工厂对象ServletFileUpload upload = new ServletFileUpload(factory); // 创建一个新的文件上传对象int size = 100 * 1024 * 1024; // 最大上传文件,不超过10MList<FileItem> fileItemList = new ArrayList<FileItem>();fileItemList = upload.parseRequest(request);// 解析上传请求System.out.println(fileItemList.size());for (FileItem fileItem : fileItemList) {if (fileItem.isFormField()) {// 判断是否为文件域System.out.println("属性名是:" + fileItem.getFieldName());System.out.println("属性值是:" + fileItem.getString("utf-8"));} else {String fileName = fileItem.getName(); // 获取文件名if (fileName != null && !fileName.equals("")) { // 判断是否选择了文件long upFileSize = fileItem.getSize(); // 上传文件大小System.out.println("上传文件" + (upFileSize / 1024 / 1024) + "M");if (upFileSize > size) {writer.write("文件超出上限100M,上传失败");return;}String suffix = fileName.substring(fileName.lastIndexOf("."));// 取文件名的后缀// 得到不重复的文件名,这一步是为了防止同时上传两个同名文件而做的,避免文件名重复Date dt = new Date(System.currentTimeMillis());SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmssSSS");serverFileName = fmt.format(dt);serverFileName = serverFileName + suffix;serverFilePath = fileDir + "/" + serverFileName;File serverFile = new File(serverFilePath);fileItem.write(serverFile);} else {writer.write("您未选择文件,请重新选择文件");return;}}}writer.write("操作成功");} else {writer.write("前端传文件enctype属性设置错误");}} catch (Exception e) {e.printStackTrace();} finally {if (writer != null) {writer.flush();writer.close();}}}

0 0
原创粉丝点击