实例代码及注解
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
List types=Arrays.asList(".jpg",".gif",".avi",".txt"); //这个用法
try{
DiskFileItemFactory factory=new DiskFileItemFactory();
//创建解析工厂
factory.
setSizeThreshold(1024*1024);
//指定内存缓冲区大小
/ /指定临时文件存储位置 this.getServletContext().getRealPath这个位置是哪里?
factory.
setRepository(
new File(this.getServletContext().getRealPath("/temp")));
ServletFileUpload upload=new ServletFileUpload(factory);
//创建解析器
//定义监听器,根据解析器,生成进度条,实现
ProgressListener接口并实现其方法
upload.
setProgressListener(new ProgressListener() {
public void update(long pBytesRead, long pContentLength, int pItems) {
System.out.println("当前已解析:"+
pBytesRead);
//用进度条插件生成pBytesRead
}
});
upload
.setFileSizeMax(1024*1024*5);
//设置文件大小限制
if(!upload.
isMultipartContent(request)){
//判断是否是multipart/form-data。
若不是,则按传统方式处
request.getParameter("username");
return;
}
//以下解决文件上传乱码,但不能解决普通字段乱码。设置request.setCharacterEncoding("UTF-8")也不行,
upload.
setHeaderEncoding
("UTF-8");
//*****************
List list=upload.
parseRequest(request);
//调用解析器解析request.得到保存了所有上传数据的list
for(FileItem fileitem:list){
//迭代list集合,获得封装了每个输入项数据的fileItem
if(fileitem.
isFormField()){ /
/判断item的类型,如果是普通字段,则直接获取数据,
String name=fileitem.getFieldName();
String inputValue= fileitem.getString("UTF-8");
//解决普通字段乱码,也可用以以两行代码
/*
String inputValue=fileitem.getString();
inputValue=new String(inputValue.getBytes("iso8859-1"),"UTF-8");*/
}else{
//
如果为上传文件,则调用流获取数据写到本地硬盘
String filename=fileitem.getName().substring(
fileitem.getName().lastIndexOf("\\")+1);
//通过文件名对文件是否存在做判断,判断用户是否有上传文件过来。
if(filename==null||filename.trim().equals("")){
continue;
// 注意continue用法;
}
String ext=filename.
substring(filename.
lastIndexOf(".")); //获取扩展名并判断
if(!types.
contains(ext)){
request.setAttribute("message", "本系统不支持"+ext+"这种类型");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
System.out.println("fileitem.getName="+fileitem.getName());
System.out.println("fileitem.getFieldName="+fileitem.getFieldName());
System.out.println(fileitem.getName().lastIndexOf("\\")+1);
//这句是错的
InputStream in=new InputStream(
fileitem
);但这句对
FileInputStream in=new FileInputStream(file);
InputStream in=fileitem.getInputStream();
//读取输入流
byte[] buffer=new byte[1024];
int len=0;
String uuidFileName=generateFileName(filename);
String savepath=generateSavePath(this.getServletContext().getRealPath("/WEB-INF/upload"), uuidFileName);
//注意上传文件存放于外界无法访问的位置,
System.out.println(this.getServletContext().getRealPath("/WEB-INF/upload"));
FileOutputStream out=
new FileOutputStream(savepath+
File.separator+uuidFileName);
//File.separator与"\\"作用相同,但不受平台影响。
while((len=in.read(buffer))>0){
out.write(buffer, 0, len);
}
in.close();
out.close();
fileitem.delete();
//最后一定要记得,删除临时文件
}
}
//两次catch,及catch中转发,这个技巧
}
catch (
FileUploadBase.FileSizeLimitExceededException e) {
//注意:视频课程中,上传文件代码是当作方法,写在工具类中,但这个异常
FileUploadBase.FileSizeLimitExceededException
的代码却并为放在工具类中跳转到jsp,而是抛到调用层(serlvet层)再跳转jsp,不知这样做有什么好处??
request.setAttribute("message", "文件大小不能超5M");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
catch(Exception e){
throw new RuntimeException(e);
}
request.setAttribute("message", "上传成功");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
//为避免同一文件夹中文件太多,将文件保存路径按文件名hashcode后四位生成。
public String generateSavePath(String path,String uuidFileName){
int hashcode=uuidFileName
.hashCode();
int dir1=hashcode&15;
int dir2=(hashcode>>4)&0xf;
String savepath=path+File.separator+dir1+File.separator+dir2;
File file=new File(savepath);
if(!
file.exists()){
file.
mkdirs();
//mkdir与mkdirs有何区别?
}
return savepath;
}
//为避免文件同名,系统生成全球唯一的文件名。
public String generateFileName(String filename){
return
UUID.randomUUID().toString()+"_"+filename;
}
//还有部分说明内容,参阅QQ笔记
??this.getServletContext().getRealPath("/WEB-INF/upload")+"\\"+filename这句话到底会返回一个什么样的路径呢?