`
shootyou
  • 浏览: 84162 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

从form的enctype属性到Content-Type再到request.getInputStream()

 
阅读更多

还是一个异常引发的故事:

需要实现一个手机客户端行为分析的需求,手机客户端需要上传一些数据文件。手机客户端通过http协议post方式上传数据文件的时候,我们发现在服务器端无法通过request.getInputStream()获取到相应的数据,调用request.getInputStream()读取数据里头啥都木有。


经过各种尝试我们注意到如下的情况:

1.在不做任何修改的情况下,调用request.getParameter()可以获取到部分数据,即url拼接参数的数据。

2.在不做任何修改的情况下,如果在之前任何地方都不调用request.getParameter(),而是直接调用request.getInputStream()是可以获取到数据的。

3.原来客户端使用默认的请求头Content-Type:application/x-www-form-urlencoded,修改此值为multipart/form-data或者application/octet-stream之后,通过request.getInputStream()可以获取到数据,即使之前调用过request.getParameter()。


最后的解决方法当然是客户端修改Content-Type,因为服务器端request.getInputStream()的方法不方便修改。今天具体分析下里头的原理。


一.从form的enctype属性到Content-Type

写html的时候我们都知道form有个属性enctype,默认值是application/x-www-form-urlencoded,这个值表示会将表单数据用&符号做一个简单的拼接。例如:


我们注意到这个时候Content-Type为application/x-www-form-urlencoded。

如果enctype的值为multipart/form-data,这个值一般用于表单中包含文件上传的情况,它会将表单中的数据使用一个boundary作为分隔上传。例如:


我们注意到这个时候Content-Type也相应的变为multipart/form-data,同时后面还加上了分隔符boundary的描述。

所以,其实form的enctype属性某种程度上决定了Content-Type值和请求body里头的数据格式。

详细的可以参考:http://imzc.net/archives/131


二.从Content-Type到request.getInputStream()


上面说到了form的处理情况,但是其实如果我们不是使用浏览器,而是自己实现的客户端来传递数据的话,这些头信息就得都由自己处理。

所以上面就出现了,上传文件的时候仍然使用了application/x-www-form-urlencoded的不标准用法。

但是为啥Content-Type会影响request的处理呢?这得从request的一些实现说起。

request.getParameter()、 request.getInputStream()、request.getReader()这三种方法是有冲突的,因为流只能被读一次。

比如:当form表单内容采用 enctype=application/x-www-form-urlencoded编码时,先通过调用request.getParameter() 方法得到参数后,再调用 request.getInputStream()或request.getReader()已经得不到流中的内容,因为在调用 request.getParameter()时系统可能对表单中提交的数 据以流的形式读了一次,反之亦然。

当form表单内容采用 enctype=multipart/form-data编码时,即使先调用request.getParameter()也得不到数据,但是这时调用 request.getParameter()方法对 request.getInputStream()或request.getReader()没有冲突,即使已经调用了 request.getParameter()方法也 可以通过调用request.getInputStream()或request.getReader()得 到表单中的数据,而request.getInputStream()和request.getReader()在同 一个响应中是不能混合使用的,如果混合使用就会抛异常。


更多也可以参考:http://robert-liu.iteye.com/blog/713568


分享到:
评论

相关推荐

    解决java enctype multipart form-data文件上传传值问题

    ### 解决Java enctype "multipart/form-data" 文件上传传值问题 在Java Web开发中,处理文件上传是一项常见的任务。特别是当涉及到使用`multipart/form-data`作为表单的编码类型时,这种需求更为突出。本文将深入...

    浅谈图片上传利用request.getInputStream()获取文件流时遇到的问题

    "浅谈图片上传利用request.getInputStream()获取文件流时遇到的问题" 本文讨论了使用request.getInputStream()获取文件流时遇到的问题,并提供了两种获取文件流的方式,分别是使用DataInputStream和...

    崔希凡JavaWeb笔记day22-day24

    - **request.getParameter("xxx")**: 在表单的enctype设置为`multipart/form-data`时,此方法将不再有效。此时它总是返回`null`。 - **ServletInputStream request.getInputStream()**: 包含整个请求的数据,包括...

    java 编写文件上传类简单易用

    在文件上载和表单提交的过程中,有两个指的关心的问题,一是上载的数据是是采用的那种方式的编码,这个问题的可以从 Content-Type 中得到答案,另一个是问题是上载的数据量有多少即 Content-Length ,知道了它,就...

    上传文件及将大数据写入数据库并通过页面访问

    为了能够上传文件,需要设置表单的`enctype`属性为`multipart/form-data`。这表示表单数据将以特殊的方式进行编码,使得文件内容可以被发送到服务器。 #### 1.3 表单数据格式 当提交包含文件的表单时,浏览器会将...

    java上传下载文件

    当表单的`enctype`属性设置为`multipart/form-data`时,提交的数据将被组织成特殊的格式,即每个文件和其他表单字段都以特定的边界字符串(boundary)进行分割。 例如,假设边界字符串为`-------------------------...

    Servlet实现文件上传与下载

    在前端页面设计时,需要注意的是表单提交方式必须设置为`POST`,同时需要指定`enctype`属性为`multipart/form-data`,这样才能正确地传输文件数据。 ```html <form action="accept.jsp" method="post" enctype=...

    servlet+commons-fileupload-1.1.1.jar上传文件源码

    在HTML表单设计上,确保`enctype`属性设置为`multipart/form-data`,以便支持文件上传: ```html <form action="UploadServlet" method="post" enctype="multipart/form-data"> <input type="file" name="fileTo...

    jsp实现文件上传下载的程序示例.docx

    - `enctype` 属性需设为 `multipart/form-data`。这是因为文件数据通常较大且包含二进制内容,这种方式能确保数据以正确的格式传输。 例如: ```html <form action="file?file=upload" method="post" enctype=...

    文件上传原理.pdf

    1. **HTML表单设置**:为了实现文件上传功能,需要在HTML表单中添加`<input type="file">`元素,并设置表单的`enctype`属性为`multipart/form-data`。这告诉浏览器以多部分格式提交表单数据,其中包含文件数据。 ...

    使用Servlet处理一个上传的文件

    <form action="upload" method="post" enctype="multipart/form-data"> 选择文件:<input type="file" name="filename" value="" /> <input type="submit" value="Upload" name="upload" /> </form> ``` ...

    jsp上传下载的文件的代码

    1. 创建HTML表单:在`index.html`中,我们创建了一个包含`<form>`元素的表单,其中`enctype`属性设置为`multipart/form-data`,这是处理文件上传所必需的。用户可以通过`<input type="file">`标签选择要上传的文件。...

    jsp实现文件上传和下载(代码及说明).pdf

    ServletInputStream sis = request.getInputStream(); // ... // 创建临时文件并写入输入流 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tmpFile)); byte[] buffer = new byte...

    Servlet实现文件上传,可多文件上传示例

    表单的`action`属性应指向处理文件上传的Servlet,如`FileUpLoad`,并且`enctype`属性应设置为`multipart/form-data`,以指示文件上传: ```html <form action="FileUpLoad" enctype="multipart/form-data" method=...

    文件的上传下载 java

    - 从服务器读取文件内容并写入到响应输出流中: ```java OutputStream out = response.getOutputStream(); File file = new File(filePath); // 服务器上文件的路径 Files.copy(file.toPath(), out); out....

    JavaWeb 文件的上传和下载功能简单实现代码

    <form enctype="multipart/form-data" action="${pageContext.request.contextPath }/servlet/uploadServlet2" method="post" > <input type="text" name="name"/> <input type="file" name="photo"/> ...

    Struts2文件的上传和下载

    同时,需要设置响应头的`Content-Type`和`Content-Disposition`,以便浏览器知道如何处理这个响应。 5. 安全性考虑:在实际应用中,需要注意文件大小限制、文件类型检查、防止路径遍历攻击等安全问题。Struts2提供...

    JSP单文件上传代码.txt

    3. **`enctype`属性**:设置为`multipart/form-data`,这是文件上传所必需的,因为只有这种编码类型可以支持文件数据的传输。 4. **`name`属性**:定义上传文件的名称,在后端可以通过这个名称来获取文件流。 #### ...

    JSP 上传和下载

    1. **表单设置**:要实现文件上传,首先需要在JSP页面中创建一个`<form>`标签,设置`enctype="multipart/form-data"`属性,以允许传输二进制数据,如文件内容。 ```html <form action="uploadServlet" method="post...

Global site tag (gtag.js) - Google Analytics