浏览器在上传的过程中是将文件以 二进制的流 的形式提交到服务器端.
1 准备一个form表单,里面有一个上传,form表单的类型必需是multipart/form-data
2 准备一个上传的Servlet,到后台接收传过来的普通表单数据 与 文件(二进制)
3 导入相应的FileUpload jar包 (commons-fileupload-1.2.2.jar ,commons-io-1.4.jar)
重要:上传时,我们表单的请求类型必需设置成multipart/form-data . 上传的method必需是POST的
完成文件上传重要方法:fileItem.write(File file);
FileItemd对象就是从request中获得数据对象,通过调用它的write把其中的数据写入到磁盘文件(File file)
常见问题及其解决方案:
1. 上传文件对象封装----CFile对象 ,可以解决 多个文件上传 及其对应属性的属性很多问题。
2. FileUtil.java 工具类 虽然可以完成上传 但是 拿不到普通表单字段值,文件上传后,我们拿到不到上传的文件的数据。
解决办法:准备两个容器(就是集合),然后一个容器装普通表单,另一个容器装上传的文件数据。把这个容器交给工具类,工具类拿到相应的数据后将数据放回到容器中。

1. 项目整体架构:

2. register.jsp代码
<body> <form action="UploadServlet" method="post" enctype="multipart/form-data"> 用户名:<input type="text" name="username"/><br> 密码:<input type="password" name="password"/><br> 头像1:<input type="file" name="headImg1"/><br> 头像2:<input type="file" name="headImg2"/><br> <input type="submit" value="提交"/> </form> </body>
3. UploadServlet.java代码
package com.gs.controller;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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 org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import com.gs.domain.CFile;
import com.gs.tools.FileUtil;
@WebServlet("/UploadServlet")
public class UploadServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
Map<String, String> fieldMap = new HashMap();
Map<String,CFile> filesMap = new HashMap();
FileUtil.upload(request, fieldMap, filesMap);
//拿数据
System.out.println(fieldMap);
System.out.println(filesMap);
} catch (Exception e) {
request.setAttribute("message","类型不匹配");
request.getRequestDispatcher("register.jsp").forward(request, response);
}
}
}
4. CFile.java代码
package com.gs.domain;
public class CFile {
private String filename;
private String filepath;
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public String getFilepath() {
return filepath;
}
public void setFilepath(String filepath) {
this.filepath = filepath;
}
@Override
public String toString() {
return "CFile [filename=" + filename + ", filepath=" + filepath + "]";
}
}
5. FileUtil.java 工具类代码
package com.gs.tools;
import java.io.File;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import com.gs.domain.CFile;
public class FileUtil {
//准备只支持的图片类型
private static final String[] IMG_TYPE = {"jpg","png","gif","bmp"};
public static void upload(HttpServletRequest request, Map<String,String> fieldMap,
Map<String,CFile> filesMap) {
//判断是否有一个文件上传的请求
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if(isMultipart){
//为基于磁盘的文件项创建工厂,并创建一个新的文件上传对象
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setFileSizeMax(1024*1024*2);//单个文件最大2M
upload.setSizeMax(1024*1024*5); //所有文件的请求的大小 5M
try {
//拿到每一项表单控件组成的 FileItem类型的集合
List<FileItem> items = upload.parseRequest(request);
for (FileItem fileItem : items) {
System.out.println(fileItem);
//如果是一般表单,用一般表单的处理方式
if(fileItem.isFormField()) {
//表单控件name的名称
String filedName = fileItem.getFieldName();
//表单控件name名称对应的值
String value = fileItem.getString("UTF-8");
//value = new String(value.getBytes("ISO-8859-1"),"utf-8");//也可以解决乱码问题
fieldMap.put(filedName, value);//将键值对添加到集合内
}else{//如果是文件上传的控件
//获取文件名,使用工具类:FilenameUtils解决ie浏览器拿文件全路径名的问题
String name = FilenameUtils.getName(fileItem.getName());
//获取后缀名
String ext = FilenameUtils.getExtension(name);
//验证后缀名是否满足图片类型
if(Arrays.asList(IMG_TYPE).contains(ext)) {
String randomUUID = UUID.randomUUID().toString();
//(通过upload文件夹)获取项目下的存储资源的路径
// F:\workspace\.metadata\...\文件上传\\upload
String path = request.getServletContext().getRealPath("/upload");
path = path.substring(0, path.indexOf(".metadata"));
String pa = request.getContextPath(); //项目的上下文路径,这里获取的是乱码
pa = URLDecoder.decode(pa,"utf-8");//解码
System.out.println(pa);
path=path.replace(‘/‘, ‘\\‘)+pa+"\\WebContent\\upload";
System.out.println(path);
//创建文件对象
File file = new File(path, randomUUID+"."+ext);
//将二进制流写入文件对象中
fileItem.write(file);
CFile cfile = new CFile();
cfile.setFilename(randomUUID+"."+ext);
cfile.setFilepath(file.getAbsolutePath());
filesMap.put(randomUUID+"."+ext,cfile);
}else {
throw new RuntimeException("文件类型不符合");
}
}
}
}catch (RuntimeException e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
文件下载可以有两种方法:
1. 超连接直接下载功能
2. 使用java代码经过servlet来进行下载
1. download.jsp代码
<body> <p style="color:red"> 超连接直接下载功能 </p> <a href="download/俄罗斯方块.html" download="俄罗斯方块">俄罗斯方块.html</a><br /> <a href="download/金玟岐 - 岁月神偷.mp3" download="岁月神偷">金玟岐 - 岁月神偷.mp3</a><br /> <a href="download/fun.mp4" download="fun视频">fun.mp4</a><br /> <a href="download/2.jpg" download="二次元图片">2.jpg</a><br /> <p style="color:red"> 使用java代码经过servlet来进行下载 </p> <a href="DownloadServlet?filename=俄罗斯方块.html">俄罗斯方块.html</a><br /> <a href="DownloadServlet?filename=金玟岐 - 岁月神偷.mp3">金玟岐 - 岁月神偷.mp3</a><br /> <a href="DownloadServlet?filename=fun.mp4">fun.mp4</a><br /> <a href="DownloadServlet?filename=2.jpg">2.jpg</a><br /> </body>
2. DownloadServlet.java代码
package com.gs.controller;
import java.io.File;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/DownloadServlet")
public class DownloadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String pa = request.getContextPath(); //项目的上下文路径,这里获取的是乱码
pa = URLDecoder.decode(pa,"utf-8");//解码
String filename = request.getParameter("filename");
String path = request.getServletContext().getRealPath("/download");
path = path.substring(0, path.indexOf(".metadata"));
System.out.println(path); //F:\workspace
path=path.replace(‘/‘, ‘\\‘)+pa+"\\WebContent\\download";
System.out.println(path); //F:\workspace\/文件上传和下载\WebContent\download
//将指定路径的文件绑定成File对象
File file = new File(path,filename);
//设置浏览器不能直接打开文件
response.setContentType("application/x-msdownload");
//解决浏览器下载文件没有后缀名和文件名问题
String userAgent = request.getHeader("User-Agent");
if(userAgent.contains("MSIE")) {
//IE浏览器
filename = URLEncoder.encode(filename,"UTF-8");
}else {
//其他浏览器
filename = new String(filename.getBytes("UTF-8"),"ISO-8859-1");
}
response.setHeader("Content-Disposition","attachment;filename="+filename);
//将文件以流的形式输出到页面中下载
Files.copy(Paths.get(file.getAbsolutePath()), response.getOutputStream());
}
}
页面显示:

原文:https://www.cnblogs.com/gshao/p/10389389.html