java web上传、下载文件源码以及应该注意的问题

时间:2022-08-28 12:10:51

      在使用jsp上传文件给后台时需要注意的几点:

        upload.setHeaderEncoding("UTF-8");//解决上传文件名的中文乱码
  //下面这句代码并不能解决form提交中文数据乱码的问题(表单为文件上传的时候)
  // request.setCharacterEncoding
   // 所以只能手工转换
   String value=item.getString();

   value=new String(value.getBytes("ISO8859-1"),"UTF-8");
  //也可以这样写
  String value=item.getString("UTF-8");


2.为了保证服务器安全,上传文件应该放在外界无法直接访问的目录


3.为了防止文件名重复,需要为每次上传的文件生成一个唯一的文件名


4.为了防止同一个目录下文件过多导致访问变慢的问题,需要将上传文件尽量打散(多个文件夹)
  这里使用的是hash算法。


5.要限制上传文件最大值
  
6.想确保临时文件被删除,需要在上传完成后(流已关闭),调用item.delete();


7.限制文件的类型,收到上传文件名时,通过文件后缀名判断


8.监听文件上传进度


上传界面代码:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/UploadServlet1" enctype="multipart/form-data" method="post">
上传用户:<input type="text" name="username"><br>
上传文件1: <input type="file" name="file1">${message }<br>
上传文件2: <input type="file" name="file2">${message }<br>
<input type="submit" value="提交">
</form>

</body>
</html>


servlet代码:

package com.wz.servlet;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Set;
import java.util.UUID;

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.FileUploadBase;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.tomcat.util.http.fileupload.RequestContext;

/**
* Servlet implementation class UploadServlet1
*/
@WebServlet("/UploadServlet1")
public class UploadServlet1 extends HttpServlet {
private static final long serialVersionUID = 1L;

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

request.getParameter("username");

// 得到上传目录
String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");
try {
DiskFileItemFactory factory = new DiskFileItemFactory();
//如果文件大于缓冲区大小(默认为10k),则使用临时文件保存数据,下面是设置临时文件的目录
factory.setRepository(new File(this.getServletContext().getRealPath("/WEB-INF/temp")));
ServletFileUpload upload = new ServletFileUpload(factory);
//监听文件上传进度
upload.setProgressListener(new ProgressListener() {
//第一个参数是已经读取多少,第二个是当前文件大小,第三个是当前是第几个文件
@Override
public void update(long arg0, long arg1, int arg2) {
// 你的操作。。。。

}
});

if (!upload.isMultipartContent(request)) {
// 按照传统方式获取数据
return;
}

upload.setFileSizeMax(1024*1024);// 设置上传文件不大于1M
upload.setSizeMax(1024*1024*10);//上传总量
upload.setHeaderEncoding("UTF-8");
List<FileItem> list = upload.parseRequest(request);
for (FileItem item : list) {
if (item.isFormField()) {
// fileItem中封装的是普通输入项的数据
String name = item.getFieldName();
String value = item.getString();
value = new String(value.getBytes("ISO8859-1"), "UTF-8");
System.out.println(name + "=" + value);
} else {
if(item.getName()==null||item.getName().trim().equals("")){
continue;
}
// fileItem中封装的是上传文件
String filename = item.getName();
filename = filename.substring(filename.lastIndexOf("\\") + 1);

InputStream in = item.getInputStream();
// 生成唯一文件名
String savaFileName = makeName(filename);
// 根据唯一文件名的hash码生成子目录
String savePaths = makePath(savaFileName, savePath);
FileOutputStream out = new FileOutputStream(savePaths + "\\" + savaFileName);
byte buffer[] = new byte[1024];
int len = 0;
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
in.close();
out.close();
//删除临时文件操作,可以确保临时文件删除,此操作必须在流关闭之后
item.delete();
}
}
}
catch(FileUploadBase.FileSizeLimitExceededException e){
request.setAttribute("message", "上传文件过大!");
request.getRequestDispatcher("/upload.jsp").forward(request, response);
return;
}
catch (Exception e) {
e.printStackTrace();
}
// response.getWriter().write("ewqeqweqweqw");
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}

public String makeName(String filename) {
return UUID.randomUUID().toString() + "_" + filename;
}

public String makePath(String filename, String savePath) {
int hashcode = filename.hashCode();
int dir1 = hashcode & 0xf;
int dir2 = hashcode & 0xf0;
String dir = savePath + "\\" + dir1 + "\\" + dir2;
File file = new File(dir);
if (!file.exists()) {
file.mkdirs();// 注意此处是mkdirs而不是mkdir,因为需要生成二级目录
}
return dir;
}

}



显示文件jsp代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:forEach var="me" items="${map }">
<%-- 在URL参数中如果出现非ASCII码字符,需要先进行编码 --%>
<c:url value="/DownloadServlet" var="downurl">
<c:param name="filename" value="${me.key }"></c:param>
</c:url>
${me.value }<a href="${downurl }">下载</a><br>
</c:forEach>
</body>
</html>

servlet:

package com.wz.servlet;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
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;

/**
* Servlet implementation class ListFileServlet
*/
@WebServlet("/ListFileServlet")
public class ListFileServlet extends HttpServlet {
private static final long serialVersionUID = 1L;


/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
String filepath= this.getServletContext().getRealPath("/WEB-INF/upload");
Map map=new HashMap<>();
listfile(new File(filepath),map);
request.setAttribute("map", map);
request.getRequestDispatcher("/WEB-INF/listfile.jsp").forward(request, response);
}
//递归遍历文件
public void listfile(File file,Map map){
if(!file.isFile()){
File files[]=file.listFiles();
for(File f:files){
listfile(f,map);
}
}else{
String realname= file.getName().substring(file.getName().indexOf("_")+1);
map.put(file.getName(), realname);
}
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}

}



下载servlet:
package com.wz.servlet;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* Servlet implementation class DownloadServlet
*/
@WebServlet("/DownloadServlet")
public class DownloadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

String filename = request.getParameter("filename");
// 防止乱码
request.setCharacterEncoding("UTF-8");
String path = makePath(filename,this.getServletContext().getRealPath("/WEB-INF/upload"));
File file= new File(path+"\\"+filename);
if(file.exists()){
//通知文件以下载形式访问文件
String realname= filename.substring(file.getName().indexOf("_")+1);
response.setHeader("content-type", "zip");
response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(realname,"UTF-8"));
FileInputStream in =new FileInputStream(path+"\\"+filename);
OutputStream out=response.getOutputStream();
byte buffer[]=new byte[1024];
int len=0;
while((len=in.read(buffer))>0){
out.write(buffer,0,len);
}
in.close();
out.close();
}else{
System.out.println("资源已删除");
}
}

/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}

public String makePath(String filename, String savePath) {
int hashcode = filename.hashCode();
int dir1 = hashcode & 0xf;
int dir2 = hashcode & 0xf0;
String dir = savePath + "\\" + dir1 + "\\" + dir2;
File file = new File(dir);
//if (!file.exists()) {
//file.mkdirs();// 注意此处是mkdirs而不是mkdir,因为需要生成二级目录
//}
return dir;

}

}