javaweb文件上传
一、初始代码
package com;
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 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.*;
import java.util.List;
import java.util.UUID;
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("utf-8");
List<FileItem> fileItems=null;
try {
fileItems = upload.parseRequest(req);
} catch (FileUploadException e) {
e.printStackTrace();
}
for (FileItem item : fileItems) {
if(item.isFormField()){//普通表单数据
}else{
String name = item.getName();
String realPath = req.getServletContext().getRealPath("/WEB-INF/load/");//得到数据存储的真实路径
InputStream is = item.getInputStream();
FileOutputStream fos = new FileOutputStream(new File(file,newName));
byte[] bytes = new byte[1024 * 1024 * 10];
while ((is.read(bytes))!=-1){
fos.write(bytes);
}
fos.close();
is.close();
}
}
}
}
}
二、优化方法
1.为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。
代码如下(示例):
req.getServletContext().getRealPath("/WEB-INF/load/");//得到数据存储的真实路径
2.为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。
代码如下(示例):
UUID uuid = UUID.randomUUID();
String prefix = uuid.toString();
String newName = prefix+"_"+name;
。
3.为防止一个目录下面出现太多文件,要使用hash算法打散存储。
String name = item.getName();
String realPath = req.getServletContext().getRealPath("/WEB-INF/load/");//得到数据存储的真实路径
int hashcode = name.hashCode();
int dir1 = hashcode&0xf; //0--15
int dir2 = (hashcode&0xf0)>>4; //0-15
System.out.println(realPath);
File file = new File(realPath+dir1+"//"+dir2);
4.要限制上传文件的最大值。
upload.setFileSizeMax(1024*1024*3);//设置上传的单个文件的最大值
5.要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。
String suffix = name.split("\\.")[1].toLowerCase();//获取后缀
if(suffix.equals("jpg")||suffix.equals("png")){
}
此处 不严谨,因为文件名中可能包含“.”,例如1.1.2.jpg
三、最终代码
package com;
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 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.*;
import java.util.List;
import java.util.UUID;
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
DiskFileItemFactory factory = new DiskFileItemFactory();//获取工厂类
ServletFileUpload upload = new ServletFileUpload(factory);//获取上传解析器
upload.setHeaderEncoding("utf-8");
upload.setFileSizeMax(1024*1024*3);//设置上传的单个文件的最大值
List<FileItem> fileItems=null;
try {
fileItems = upload.parseRequest(req);
} catch (FileUploadException e) {
e.printStackTrace();
}
for (FileItem item : fileItems) {
if(item.isFormField()){//普通表单数据
}else{
String name = item.getName();
String realPath = req.getServletContext().getRealPath("/WEB-INF/load/");//得到数据存储的真实路径
int hashcode = name.hashCode();
int dir1 = hashcode&0xf; //0--15 //使用hashcode建立文件夹
int dir2 = (hashcode&0xf0)>>4; //0-15
System.out.println(realPath);
File file = new File(realPath+dir1+"//"+dir2);
if(!file.exists()){
file.mkdirs();
}
String suffix = name.split("\\.")[1].toLowerCase();//获取后缀
if(suffix.equals("jpg")||suffix.equals("png")){
UUID uuid = UUID.randomUUID(); //使用uuid得到一个唯一前缀,防止文件名重复
String prefix = uuid.toString();
String newName = prefix+"_"+name;
InputStream is = item.getInputStream();
FileOutputStream fos = new FileOutputStream(new File(file,newName));
byte[] bytes = new byte[1024 * 1024 * 10];
while ((is.read(bytes))!=-1){
fos.write(bytes);
}
fos.close();
is.close();
}
else{
resp.setContentType("text/html;charset=utf-8");
PrintWriter out = resp.getWriter();
out.println("<h1>上传格式不正确</h1>");
}
}
}
}
}