一、如何向服务器上传一个本地图片?
首先,Fileupload的使用场景:比如说提交作业,更换头像。
需要一个form表单,表单有如下三个要求
- input type = file
- method = post
- enctype=multipart/form-data
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//response给我们封装现存的响应输出流
//response.getOutputStream
//request给我们封装好现存的输入流
ServletInputStream inputStream = request.getInputStream();
String realPath = getServletContext().getRealPath("upload/1.jpg");
File file = new File(realPath);
//防止父目录不存在,引发异常,如果父目录不存在,则创建
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
FileOutputStream fileOutputStream = new FileOutputStream(file);
int length = 0;
byte[] bytes = new byte[1024];
while ((length = inputStream.read(bytes)) != -1){
fileOutputStream.write(bytes, 0, length);
}
fileOutputStream.close();
//inputStream可以关也可以不关,不关的话tomcat会帮助我们关闭
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
二、为什么文件会损坏?
用上述代码上传一个图片,去部署根目录下找到文件,发现文件已损坏
上传一个txt文件发现文件平白无故多出了一些WebKitFormBoundary分隔符
对于一个二进制文件,图片、音频、视频、exe文件,多出来这一部分会直接导致文件损坏。
并且普通form表单请求参数也无法获取,因为请求体中的数据结构发生了变更,之前的数据key=value&key=value拼接的,getParameter通过key可以获取到数据value,那么如果数据结构发生了变更,getParameter理应不能再用了。
所有一切的原因都是因为添加了enctype=multipart/form-data。但是如果不添加,就不会上传文件。
三、使用组件上传文件
实现步骤:
- 创建DiskFileItemFactory对象,设置缓冲区大小和临时文件目录
- 使用DiskFileItemFactory 对象创建ServletFileUpload对象,并设置上传文件的大小限制。
- (关键)调用ServletFileUpload.parseRequest方法解析request对象,得到一个保存了所有上传内容的List对象。list中的每一个元素,就是每个input的封装。
- 对list进行迭代,每迭代一个FileItem对象,调用其isFormField方法判断是否是上传文件。
- true表示为普通表单字段,则调用getFieldName、getString方法得到字段名和字段值。
- false 为上传文件,则调用getInputStream方法得到数据输入流,从而读取上传数据。
@WebServlet("/upload2")
public class UploadServlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//判断是否含有上传的文件
response.setContentType("text/html;charset=utf-8");
boolean result = ServletFileUpload.isMultipartContent(request);
if(!result){
response.getWriter().println("没有包含上传的文件");
return;
}
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置一个仓库、缓冲区,目的是为了传输大型文件时,会利用缓冲区边中转边传输
ServletContext servletContext = getServletContext();
File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
factory.setRepository(repository);
// 拿到真正去处理请求的处理器
ServletFileUpload handler =