文件上传的技术
1. JSPSmartUpload(应用在JSP上的文件上传和下载的组件)
2. FileUpload(应用在Java环境上的文件上传的功能)
3. Struts2(提供文件上传的功能)
什么是文件上传
将本地的文件通过流写入到服务器的过程
文件上传的要素
表单的提交的方式需要是POST
表单中需要有<input type=”file”>元素,需要有name属性和值。
表单form的属性enctype=”multipart/form-data”
代码演示
jsp部分代码
<form action="填写提交的路径" method="post" enctype="multipart/form-data">
<input type="text" name="textName">
<input type="file" name="filename">
<input type="submit" value="提交">
</form>
UploadFileServlet代码(mvc中控制器的代码)
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import utils.UploadUtils;
/**
* 文件上传
*/
@WebServlet("/uploadFileServlet")
public class UploadFileServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//判断enctype填写的格式是否正确
if(!ServletFileUpload.isMultipartContent(request)) {
request.setAttribute("msg", "提交的格式enctry错误");
request.getRequestDispatcher("/jsp/upload.jsp").forward(request, response);
}
try {
// 1.创建磁盘文件项工厂
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
//1.1缓冲区的大小为3M
diskFileItemFactory.setSizeThreshold(3*1024*1024);
//1.2临时文件的存放位置
String repositoryPath = getServletContext().getRealPath("/repositoryFile");
diskFileItemFactory.setRepository(new File(repositoryPath));
// 2.创建核心解析类
ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
//2.1设置文件的上传大小
servletFileUpload.setSizeMax(20*1024*1024); //总文件
servletFileUpload.setFileSizeMax(6*1024*1024);//单个文件
// 3.利用核心类解析Request,解析后会得到多个部分。返回一个List集合。List集合装的是每个部分的内容(FileItem文件项)。
List<FileItem> list = servletFileUpload.parseRequest(request);
// 4.遍历List集合,会得到代表每个部分的文件项的对象。根据文件项判断是否是文件上传项。
for (FileItem fileItem : list) {
if (fileItem.isFormField()) {
// 普通文件
String name = fileItem.getFieldName();
String value = fileItem.getString();
System.out.println(name + " " + value);
} else {
String nameFile = fileItem.getName();
//IE老版本的文件名带用户上传全路径
int indexFileName=nameFile.lastIndexOf("\\");
if(indexFileName!=-1) {
nameFile=nameFile.substring(indexFileName+1);
}
// 获得文件上传的文件的数据:
InputStream inputStream = fileItem.getInputStream();
// 获得文件上传的路径:磁盘绝对路径。
String realPath = getServletContext().getRealPath("/upload");
//获取唯一的文件名字
String uuidFileName=UploadUtils.getUuidFileName(nameFile);
//进行目录分离:
String uuidFilePath=UploadUtils.getRealPath(uuidFileName);
String newPath=realPath+uuidFilePath;
File file=new File(newPath);
if(!file.exists()) {
file.mkdirs();
}
// 创建一个输出流,写入到设置的路径中。
FileOutputStream ou = new FileOutputStream(newPath+"\\"+uuidFileName);
int len = 0;
byte[] a = new byte[1024];
// 两个流对接:
while ((len = inputStream.read(a)) != -1) {
ou.write(a, 0, len);
}
inputStream.close();
ou.close();
}
//删除缓冲区的文件(临时文件)
fileItem.delete();
}
} catch (Exception e) {
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
utils代码
import java.util.UUID;
public class UploadUtils {
//传入文件名,返回唯一路径
public static String getUuidFileName(String filename) {
String uuid=UUID.randomUUID().toString().replace("-", "");
int indexdot=filename.lastIndexOf(".");
String newFilename=uuid+filename.substring(indexdot);
return newFilename;
}
//目录分离
public static String getRealPath(String uuidFilename) {
//获取的是二级目录,可以增加
int code1 = uuidFilename.hashCode();
int d1 = code1 & 0xf;
int code2 = code1 >>> 4;
int d2 = code2 & 0xf;
return "/"+d1+"/"+d2;
}
}
文件上传的原理分析
文件上传到同一个目录下(文件过多的问题)
问题描述
现在所有的用户都上传文件,如果网站访问量比较大,如果都上传到同一个目录下,在同一个目录下存放的文件太多了,也会对程序有影响(其实打开该目录的时候,都会很卡,更别说读写操作)。
文件解决
目录分离
按时间分离 :按月、周、天、小时。
按用户分离 :按张三、李四。
按个数分离 :一个目录下存放3000个文件。
按目录分离算法 :按照某种特定算法进行分离。
唯一文件名获取其hashCode值,返回int类型的值(32位)
让hashCode的值 & 0xf,得出的这个值作为一级目录。
让hashCode右移4位 再& 0xf,得出的这个值作为二级目录。
以此类推。
分析算法: