浏览器会如何上传一个文件?
注意最下面那一栏,那就是这次post的实体部分,这个实体中包含着文件内容,chrome这里隐藏了文件内容,我实际传了一个内容是”123“的文本文件,完整实体部分是下面这样子:
注意第一幅图中的Content-Type属性,中间有一个”boundary“,boundary意思是”边界,界限“。其实是浏览器随机生成的一串字符串,用来界定真正文件的范围的,当我们把实体部分接收到以后,可以根据boundary来取出真正的文件。
所以,上传文件很简单有没有。
下面是测试代码:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
byte[] body = readBody(req);
String s = new String(body,"iso-8859-1");
Position p = getFilePosition(req,s);
write(body,p);
}
class Position {
int begin;//文件开头位置
int end;//文件最后一位的后一位
Position(int begin,int end) {
this.begin = begin;
this.end = end;
}
@Override
public String toString() {
return "Position{" +
"begin=" + begin +
", end=" + end +
'}';
}
}
private Position getFilePosition(HttpServletRequest request,String textBody) throws UnsupportedEncodingException {
String contentType = request.getContentType();
//那一串英文字母,用来界定文件的开头位置与结束位置
String boundaryText = contentType.substring(contentType.lastIndexOf('=') + 1,contentType.length());
//获取实际的文件开始和结束位置
int pos = 0;
pos = textBody.indexOf("\n",pos) + 1;
pos = textBody.indexOf("\n",pos) + 1;
pos = textBody.indexOf("\n",pos) + 1;
pos = textBody.indexOf("\n",pos) + 1;
//为什么是减4,因为最后那一行的上一行结尾是CRLF,即回车换行
//结合本例,也就是“123”那一行结尾是CRLF
int boundaryLoc = textBody.indexOf(boundaryText,pos) - 4;
return new Position(pos,boundaryLoc);
}
private byte[] readBody(HttpServletRequest request) throws IOException {
int dataLength = request.getContentLength();
InputStream inputStream = request.getInputStream();
byte[] body = new byte[dataLength];
int totalBytes = 0;
while (totalBytes < dataLength) {
int bytes = inputStream.read(body,totalBytes,dataLength);
totalBytes += bytes;
}
return body;
}
private void write(byte[] body,Position p) throws IOException {
OutputStream out = new FileOutputStream("/tmp/1");
out.write(body,p.begin,p.end - p.begin);
out.close();
}
}