参考官网
官网
官方API
日常生活中经常会使用文件上传下载,比如:个人头像上传 、半夜发美食朋友圈
Apache Commons FileUpload 文件上传 为我们简化底层IO代码的实现
1、支持多文件上传
本案基于 H5+ Servlets 实现
一、引入相关依赖及位置图
commons-fileupload-1.4.jar
commons-io-2.11.0.jar

资源链接:
https://pan.baidu.com/s/1NKuCbsKlSrjPp5lbi1QMlA
提取码: grxy
–来自百度网盘超级会员v6的分享
二、版本要求 建议 JDK 1.8

三、制作上传所使用的网页
注意事项
1、上传文件时,form表单的method属性必须设置为post,不能是get
2、上传文件时,需要在表单属性中添加enctype属性,该属性用于设置表单提交数据的编码方式,由于文件传至服务器时与一般文本类型的编码方式不同,需要设置为multipart/form-data。
PS:enctype属性共有三个值,如下
-
application/x-www-form-urlencoded,默认值,该属性值主要用于处理少量文本数据的传递,处理二进制数据、非ASCII编码文本时,效率低;
-
multipart/form-data,上传二进制数据,只有使用了multipart/form-data属性值才能完整地传递文件数据;
-
text/plain,主要用于向服务器传递大量文本数据,如电子邮件、发布长篇新闻等。
网页代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>使用Commons-FileUpload组件实现文件上传</title>
</head>
<body>
<!-- ${pageContext.request.contextPath}/FileUpload JSP网页可用 -->
<form action="FileUpload" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="userName">
<!-- 加上multiple属性,可以一次上传多个文件 -->
选择文件:<input type="file" name="myFile" multiple>
<input type="submit" value="上传">
</form>
</body>
</html>
四、后台处理程序 此时使用的Java中的Servlet
后台源码
@WebServlet(description = "FileUpload", urlPatterns = { "/FileUpload" })
public class FileUpload extends HttpServlet {
private String path = "../temp/image";
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html");
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
String userName="";
StringBuffer fileStr = new StringBuffer();
if ( !isMultipart ){
return;
}
String savePath = request.getServletContext().getRealPath("/") + path;
try {
FileItemFactory factory=new DiskFileItemFactory();
ServletFileUpload upload=new ServletFileUpload(factory);
List<FileItem> itemList=upload.parseRequest(request);
Iterator<FileItem> iterator=itemList.iterator();
while ( iterator.hasNext() ){
FileItem fileItem = iterator.next();
System.out.println( fileItem );
if (fileItem.isFormField( )){
if (fileItem.getFieldName().equals("userName")){
userName=fileItem.getString("UTF-8");
}
}else {
String fileUpName = fileItem.getName();
System.out.println( fileUpName );
String newFileUpName = UUID.randomUUID().toString().replaceAll("-", "") + "-" + fileUpName;
File uplodeFile = new File( savePath, newFileUpName);
fileItem.write( uplodeFile );
fileStr.append( newFileUpName + "、");
}
}
fileStr.replace(fileStr.lastIndexOf("、"), fileStr.length(), "");
PrintWriter writer = response.getWriter();
writer.print("<script>alert('用户"+userName+"上传了文件"+fileStr+"')</script>");
}catch (Exception e){
e.printStackTrace();
}
}
}
五、注意事项
1、异常提示: 文件已经存在
异常代码
org.apache.commons.io.FileExistsException: File element in parameter 'null' already exists: 'C:\Users\ASUS\Desktop\down\apache-tomcat-9.0.52\webapps\jw2001-5\..\temp\image\fb1925394d814b5aaead6a52695683c8-屏幕截图(1).png'
异常图

分析思路
检查发现关键代码
fileItem.write( uplodeFile );
文件输出备用代码
InputStream is = fileItem.getInputStream();
OutputStream os = new FileOutputStream( uplodeFile );
byte[] bt = new byte[ (int) fileItem.getSize() ];
int len = 0;
while( ( len = is.read( bt ) ) != -1 ) {
os.write(bt, 0 , len);
}
os.close();
is.close();
官方解释如下
void write(File file)
throws Exception
A convenience method to write an uploaded item to disk. The client code is not concerned with whether or not the item is stored in memory, or on disk in a temporary location. They just want to write the uploaded item to a file.
This method is not guaranteed to succeed if called more than once for the same item. This allows a particular implementation to use, for example, file renaming, where possible, rather than copying all of the underlying data, thus gaining a significant performance benefit.
Parameters:
file - The File into which the uploaded item should be stored.
Throws:
Exception - if an error occurs.
检查源码
@Override
public void write(File file) throws Exception {
if (isInMemory()) {
FileOutputStream fout = null;
try {
fout = new FileOutputStream(file);
fout.write(get());
fout.close();
} finally {
IOUtils.closeQuietly(fout);
}
} else {
File outputFile = getStoreLocation();
if (outputFile != null) {
size = outputFile.length();
FileUtils.moveFile(outputFile, file);
} else {
throw new FileUploadException(
"Cannot write uploaded file to disk!");
}
}
}
底层调用了FileOutputStream进行数据的输出, 而该方法会自动创建不存在的目录
导致文件冲突 产生异常 从而未生效
错误代码
注释掉就行
if ( !uplodeFile .exists() ){
uplodeFile .createNewFile();
}
错误效果图

正常效果图
1、上传操作
2、成功提示
到此完美成功!
当然还需更多优化改进!
TODO
1、上传进度条
2、文件类型 、大小 、数量
3、文件下载