有时,在网络编程过程中需要向服务器上传文件。Multipart/form-data是上传文件的一种方式。
Multipart/form-data其实就是浏览器用表单上传文件的方式。最常见的情境是:在写邮件时,向邮件后添加附件,附件通常使用表单添加,也就是用multipart/form-data格式上传到服务器。
<form action=“/TestWeb/command=UpdatePicture” method=”post” enctype=”multipart/form-data”>
<input type=”file” name=”uploadfile1”/><br>
<input type=”file” name=”uploadfile2”/><br>
<input type=”submit” value=”uploadfile”>
</form>
![06175218_oxSm.png](http://static.oschina.net/uploads/img/201506/06175218_oxSm.png)
内容如下:
Type:multipart/form-data; boundary=-----------------------------265001916915724
-----------------------------265001916915724
Content-Disposition: form-data; name="uploadfile1"; filename="web.txt"
Content-Type: text/plain
ChinaNetSNWide
å网æ©ç 255.255.255.255 ç®å•çš„说四个255是全广æ’IP地åã‚就是用æ¥ä»DHCPæœ åŠ¡å™¨é‚£é‡Œè•å–IP地åã‚
默认网关0.0.0.0 å³æœ¬æœº
-----------------------------265001916915724
Content-Disposition: form-data; name="uploadfile2"; filename="20080116064637581.jpg"
Content-Type: image/jpeg
ÿØÿà
-----------------------------265001916915724—
注意点一:
Header 下面boundary 有27个 -(横杆)
POST Data 下面传输每个文件的开头是有29个 -
注意点二:
观察POST Data可以发现从第一个-----------------------------265001916915724
到第二个-----------------------------265001916915724之间为一个txt文件的相关
信息。
上面form提交的servlet不用实现,只是解析了http协议,为下面模拟铺垫。
下面实现android客户端上传图片到服务端的servlet
android客户端代码
public void upload() {
Log.d(TAG, "upload begin");
HttpURLConnection connection = null;
DataOutputStream dos = null;
FileInputStream fin = null;
String boundary = "---------------------------265001916915724";
// 真机调试的话,这里url需要改成电脑ip
// 模拟机用10.0.0.2,127.0.0.1被tomcat占用了
String urlServer = "http://10.0.0.2:8080/TestWeb/command=UpdatePicture";
String lineEnd = "\r\n";
String pathOfPicture = "/sdcard/aaa.jpg";
int bytesAvailable, bufferSize, bytesRead;
int maxBufferSize = 1*1024*512;
byte[] buffer = null;
try {
Log.d(TAG, "try");
URL url = new URL(urlServer);
connection = (HttpURLConnection) url.openConnection();
// 允许向url流中读写数据
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(true);
// 启动post方法
connection.setRequestMethod("POST");
// 设置请求头内容
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "text/plain");
// 伪造请求头
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
// 开始伪造POST Data里面的数据
dos = new DataOutputStream(connection.getOutputStream());
fin = new FileInputStream(pathOfPicture);
Log.d(TAG, "开始上传images");
//--------------------开始伪造上传images.jpg的信息-----------------------------------
String fileMeta = "--" + boundary + lineEnd +
"Content-Disposition: form-data; name=\"uploadedPicture\"; filename=\"" + pathOfPicture + "\"" + lineEnd +
"Content-Type: image/jpeg" + lineEnd + lineEnd;
// 向流中写入fileMeta
dos.write(fileMeta.getBytes());
// 取得本地图片的字节流,向url流中写入图片字节流
bytesAvailable = fin.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
bytesRead = fin.read(buffer, 0, bufferSize);
while(bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fin.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fin.read(buffer, 0, bufferSize);
}
dos.writeBytes(lineEnd+lineEnd);
//--------------------伪造images.jpg信息结束-----------------------------------
Log.d(TAG, "结束上传");
// POST Data结束
dos.writeBytes("--" + boundary + "--");
// Server端返回的信息
System.out.println("" + connection.getResponseCode());
System.out.println("" + connection.getResponseMessage());
if (dos != null) {
dos.flush();
dos.close();
}
Log.d(TAG, "upload success-----------------------------------------");
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "upload fail");
}
}
服务端servlet
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// 利用该组件进行接收客户端上传的文件
// 需要自己加载commons-fileupload-1.2.2.jar和commons-io-2.1.jar
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
/**
* Servlet implementation class ReceivePictureFromAndroid
*/
@WebServlet("/command=UpdatePicture")
public class ReceivePictureFromAndroid extends HttpServlet {
private static final long serialVersionUID = 1L;
public ReceivePictureFromAndroid() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> list = upload.parseRequest(request);
System.out.println(list + " list " + list.size() );
for(FileItem item : list) {
String paramName = item.getFieldName();
System.out.println(paramName);
String paramValue = item.getString();
System.out.println(paramValue);
if(item.isFormField() == false) {
File f = new File("f:\\img.jpg");
item.write(f);
System.out.println("write filt success");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}