web端的文件上传和下载
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现。
对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件
的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上
传组件。这个common-fileupload上传组件的jar包可以去apache官网上面下载,也可以在struts的lib文件夹下面找到,
struts上传的功能就是基于这个实现的。common-fileupload是依赖于common-io这个包的,所以还需要下载这个包。
对于此包可以自己搜索,资源很多。
1.上传文件逻辑
下面写下逻辑层的代码:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
HttpSession session = request.getSession();
String fileExtName = null;
String realSavePath = null;
String saveFilename = null;
int filesize = 0;
/*得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全*/
String savePath = request.getSession().getServletContext().getRealPath("/WEB-INF/upload");
/*上传时生成的临时文件保存目录*/
String tempPath = request.getSession().getServletContext().getRealPath("/WEB-INF/temp");
File tmpFile = new File(tempPath);
if (!tmpFile.exists()) {
/*创建临时目录*/
tmpFile.mkdir();
}
try{
/*使用Apache文件上传组件处理文件上传步骤:
1、创建一个DiskFileItemFactory工厂*/
DiskFileItemFactory factory = new DiskFileItemFactory();
/*设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。*/
factory.setSizeThreshold(1024*100);
/*设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB
设置上传时生成的临时文件的保存目录*/
factory.setRepository(tmpFile);
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setProgressListener(new ProgressListener(){
public void update(long pBytesRead, long pContentLength, int arg2) {
System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead);
/**
*/
}
});
/**
解决上传文件名的中文乱码
*/
upload.setHeaderEncoding("UTF-8");
request.setCharacterEncoding("UTF-8");
/**
3、判断提交上来的数据是否是上传表单的数据
设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB
*/
upload.setFileSizeMax(1024*1024*100);
/**设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB*/
upload.setSizeMax(1024*1024*1000);
/**4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项*/
List<FileItem> list = upload.parseRequest(request);
for(FileItem item:list){
filesize=(int) list.get(0).getSize();
/** filesize=parse(int)list.size();*/
/**如果fileitem中封装的是普通输入项的数据*/
if(item.isFormField()){
String name = item.getFieldName();
/**解决普通输入项的数据的中文乱码问题*/
String value = item.getString("UTF-8");
System.out.println(name + "=" + value);
}else{
String filename = item.getName();
if(filename==null || filename.trim().equals("")){
continue;
}
/**注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
处理获取到的上传文件的文件名的路径部分,只保留文件名部分*/
filename = filename.substring(filename.lastIndexOf("\\")+1);
/**得到上传文件的扩展名*/
fileExtName = filename.substring(filename.lastIndexOf(".")+1);
/**如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上传的文件类型是否合法
获取item中的上传文件的输入流*/
InputStream in = item.getInputStream();
/**得到文件保存的名称*/
saveFilename = makeFileName(fileExtName);
/**得到文件的保存目录*/
realSavePath = makePath(saveFilename, savePath);
/**创建一个文件输出流*/
FileOutputStream out = new FileOutputStream(realSavePath + "\\" + saveFilename);
/**创建一个缓冲区*/
byte buffer[] = new byte[1024];
/**判断输入流中的数据是否已经读完的标识*/
int len = 0;
/** 循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据*/
while((len=in.read(buffer))>0){
/**使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中*/
out.write(buffer, 0, len);
}
in.close();
out.close();
}
}
}catch (Exception e) {
e.printStackTrace();
}
return "**路径**";
}
/**防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名*/
private String makeFileName(String fileExtName){
Calendar c = Calendar.getInstance();
SimpleDateFormat df1 = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss");
String CurDatetime = df1.format(c.getTime());
String DOCID = CurDatetime + String.valueOf(Math.random()).substring(2, 4);
DOCID = DOCID.replace(":", "").replace(" ", "").replace("-", "");
return DOCID+"."+fileExtName;
}
/**
* 为防止一个目录下面出现太多文件,要使用hash算法打散存储
*/
private String makePath(String filename,String savePath){
/**得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址*/
int hashcode = filename.hashCode();
int dir1 = hashcode&0xf; //0--15
int dir2 = (hashcode&0xf0)>>4; //0-15
/**构造新的保存目录*/
String dir = savePath + "\\" + dir1 + "\\" + dir2; //upload\2\3 upload\3\5
File file = new File(dir);
/**如果目录不存在*/
if(!file.exists()){
file.mkdirs();
}
return dir;
}
以上就是上传文件的主要逻辑代码,楼楼是是以Spring+Springmvc+Mybatis为框架进行搭建的项目工程。所以里面有一些
属于框架的东西。
2.下载文件逻辑
下面是下载的逻辑代码:
/**下载附件*/
@RequestMapping("/DownFile")
public String DownFile(HttpServletRequest request,HttpServletResponse response,String upautor)
throws ServletException, IOException{
/**得到要下载的文件*/
String fileName = request.getParameter("upautor");
String realpath=request.getParameter("realpath");
String filetype =request.getParameter("filetype");
fileName = new String(fileName.getBytes("iso8859-1"),"UTF-8");
String picgif="gif";
String picjpg="jpg";
String picpng="png";
String picbmp="bmp";
String redrect=null;
/**图片的格式有(具体分析):
* gig tif rgb dib eps jpe pcx
得到要下载的文件*/
File file = new File(realpath + "\\" + fileName);
/**处理文件名*/
String realname = fileName.substring(fileName.indexOf("_")+1);
/**设置响应头,控制浏览器下载该文件*/
/**判断附件格式,如果为图片则显示,否则下载*/
if(filetype.equals(picgif)||filetype.equals(picjpg)||filetype.equals(picpng)||filetype.equals(picbmp)){
response.setContentType(filetype);
response.setContentLength((int)file.length());
response.setHeader("Content-Disposition", "inline; filename="
+ URLEncoder.encode(realname, "UTF-8"));
InputStream in = new FileInputStream(file);
OutputStream out = response.getOutputStream();
long statistic = 0;
byte buffer[] = new byte[8192];
do {
int bytesRead = in.read(buffer);
if (bytesRead == -1)
break;
out.write(buffer, 0, bytesRead);
statistic = statistic + bytesRead;
out.flush();
} while (true);
in.close();
out.close();
redrect="redirect:/upload/showFile";
}else
{
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
/**读取要下载的文件,保存到文件输入流*/
FileInputStream in = new FileInputStream(realpath + "\\" + fileName);
/**创建输出流*/
OutputStream out = response.getOutputStream();
/**创建缓冲区*/
byte[] buffer = new byte[1024];
int len = 0;
/**循环将输入流中的内容读取到缓冲区当中*/
while((len=in.read(buffer))>0){
response.setContentType("image/jpg");
response.setContentLength(buffer.length);
/**输出缓冲区的内容到浏览器,实现文件下载*/
out.write(buffer, 0, len);
}
in.close();
out.close();
}
return "**路径**";
}
通过以上可以在web工程中实现文件的上传和下载,项目中是以图片为例,并为其设置了格式的限制,修改对应需要自适应。