Java EE中文档上传下载实现的过程和思考

2012.7.20  星期五  天气晴朗

    

    很久没有写学习文档了。今天就最近在做的文档管理模块中的文档上传和下载,写一篇实现过程的日志,仅供学习和参考。如果疑问,邮电:457151376@qq.com

那么首先,来讲讲如何实现上传。

一般文档上传和下载我们通过通用的Servlet来实现。当然也有人把代码写在JSP里面实现。实现的方式有很多种,但是原理是一样的。那么我们找一种可以持久使用和重复使用的方式。用Servlet实现上传和下载。

先给出FileUploadServletFileDownloadServlet实现的代码:

package cn.trymore.core.web.servlet;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
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 org.shengrui.oa.model.system.ModelAppUser;
import org.shengrui.oa.util.ContextUtil;

import cn.trymore.core.util.UtilApp;
import cn.trymore.core.util.UtilFile;
import cn.trymore.oa.model.system.ModelFileAttach;
import cn.trymore.oa.service.system.ServiceFileAttach;

/**
 * The servlet for file uploading.
 * 
 * @author Jeccy.Zhao
 *
 */
public class FileUploadServlet
extends HttpServlet
{

	private static final long serialVersionUID = 4757212133352817333L;
	
	/**
	 * The file attach service.
	 */
	private ServiceFileAttach serviceFileAttach = (ServiceFileAttach) UtilApp.getBean("serviceFileAttach");
	
	/**
	 * The servlet configuration
	 */
	private ServletConfig servletConfig = null;
	
	/**
	 * The file upload destination path.
	 */
	private String uploadPath = "";
	
	/**
	 * The file upload temporary path.
	 */
	private String tempPath = "";
	
	/**
	 * The file category
	 */
	private String fileCat = "others";
	
	public void init(ServletConfig servletConfig) throws ServletException
	{
		this.servletConfig = servletConfig;
		super.init(servletConfig);
	}
	
	/**
	 * Initializations, like:
	 * 
	 * 1. Define the temporary path for file upload.   <br/>
	 * 2. Define the destination path for file upload. <br/>
	 * 3. Create the above directories if not existed. 
	 * 
	 */
	public void init() throws ServletException
	{
		this.uploadPath = servletConfig.getServletContext().getRealPath("/uploads/");
		
		System.out.println(this.uploadPath);
		
		File localFile = new File(this.uploadPath);
		if (!localFile.exists())
		{
			localFile.mkdirs();
		}
		
		this.tempPath = this.uploadPath + "/temp";
		File tmpFile = new File(this.tempPath);
		if (!tmpFile.exists())
		{
			tmpFile.mkdirs();
		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	@SuppressWarnings("unchecked")
	protected void doPost(HttpServletRequest request, 
			HttpServletResponse response) throws ServletException, IOException
	{
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		
		try
		{
			DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
			diskFileItemFactory.setSizeThreshold(4096);
			diskFileItemFactory.setRepository(new File(this.tempPath));
			
			String fileIds="";
			
			ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
			List<FileItem> fileList = (List<FileItem>) servletFileUpload.parseRequest(request);
			Iterator<FileItem> itor = fileList.iterator();
			
			FileItem fileItem;
			while (itor.hasNext())
			{
				fileItem = itor.next();
				if (fileItem.getContentType() == null)
				{
					continue;
				}
				
				// obtains the file path and name
				String filePath = fileItem.getName();
				
				String fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
				// generates new file name with the current time stamp.
				String newFileName = this.fileCat + "/" + UtilFile.generateFilename(fileName);
				// ensure the directory existed before creating the file.
				File dir = new File(this.uploadPath + "/" + newFileName.substring(0, newFileName.lastIndexOf("/") + 1));
				if (!dir.exists())
				{
					dir.mkdirs();
				}
				
				// stream writes to the destination file
				fileItem.write(new File(this.uploadPath + "/" + newFileName));
				
				// storages the file into database.
				ModelFileAttach fileAttach = new ModelFileAttach();
				fileAttach.setFileName(fileName);
				fileAttach.setFilePath(newFileName);
				fileAttach.setTotalBytes(Long.valueOf(fileItem.getSize()));
				fileAttach.setNote(this.getStrFileSize(fileItem.getSize()));
				fileAttach.setFileExt(fileName.substring(fileName.lastIndexOf(".") + 1));
				fileAttach.setCreatetime(new Date());
				fileAttach.setDelFlag(ModelFileAttach.FLAG_NOT_DEL);
				fileAttach.setFileType(this.fileCat);
				
				ModelAppUser user = ContextUtil.getCurrentUser();
				if (user != null)
				{
					fileAttach.setCreatorId(Long.valueOf(user.getId()));
					fileAttach.setCreator(user.getFullName());
				}
				else
				{
					fileAttach.setCreator("Unknow");
				}
				
				this.serviceFileAttach.save(fileAttach);
				
				//add by Tang 这部分代码用于临时保存fileIds,用完后一定要注意及时销毁。
				fileIds=(String) request.getSession().getAttribute("fileIds");
				if(fileIds==null)
				{
					fileIds=fileAttach.getId();
				}
				else
				{
					fileIds=fileIds+","+fileAttach.getId();
				}
				
				response.setContentType("text/html;charset=UTF-8");
				PrintWriter writer = response.getWriter();
				writer.println("{\"status\": 1, \"data\":{\"id\":" + fileAttach.getId() + "}}");
			}
			request.getSession().setAttribute("fileIds", fileIds);
		}
		catch (Exception e)
		{
			e.printStackTrace();
			response.getWriter().write("{\"status\":0, \"message\":\"上传失败:" + e.getMessage() + "\"");
		}
	}
	
	/**
	 * Obtains the decimal formated file size.
	 * 
	 * @param size
	 * @return
	 */
	protected String getStrFileSize (double size)
	{
		DecimalFormat decimalFormat = new DecimalFormat("0.00");
		
		double byteSize;
		if (size > 1048576.0D)
		{
			byteSize = size / 1048576.0D;
			return decimalFormat.format(byteSize) + " M";
		}
		
		if (size > 1024.0D)
		{
			byteSize = size / 1024.D;
			return decimalFormat.format(byteSize) + " KB";
		}
		
		return size + " bytes";
	}
	
	public void setServletConfig(ServletConfig servletConfig)
	{
		this.servletConfig = servletConfig;
	}

	public ServletConfig getServletConfig()
	{
		return servletConfig;
	}

	public void setUploadPath(String uploadPath)
	{
		this.uploadPath = uploadPath;
	}

	public String getUploadPath()
	{
		return uploadPath;
	}

	public void setTempPath(String tempPath)
	{
		this.tempPath = tempPath;
	}

	public String getTempPath()
	{
		return tempPath;
	}

	public void setServiceFileAttach(ServiceFileAttach serviceFileAttach)
	{
		this.serviceFileAttach = serviceFileAttach;
	}

	public ServiceFileAttach getServiceFileAttach()
	{
		return serviceFileAttach;
	}

}


package cn.trymore.core.web.servlet;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 文档下载
 * @author Tang
 * 使用方法:直接写/download?path=""就可以
 */


public class FileDownloadServlet extends HttpServlet {
	/**
	 * 
	 */
	private static final long serialVersionUID = -5563238888658319929L;
	
	
	/**
	 * The servlet configuration
	 */
	private ServletConfig servletConfig = null;
	
	public void init(ServletConfig servletConfig) throws ServletException
	{
		this.servletConfig = servletConfig;
		super.init(servletConfig);
	}
	
	

	protected void service(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {

		//  服务器相对路径    
		String path = req.getParameter("path");
		//  服务器绝对路径    
		path = servletConfig.getServletContext().getRealPath("/uploads/")+"/"+path;
		
		System.out.println(path);

		//  检查文件是否存在   
		File obj = new File(path);

		if (!obj.exists()) {
			res.setContentType("text/html;charset=GBK");
			res.getWriter().print("指定文件不存在!");
			return;
		}
		//  读取文件名:用于设置客户端保存时指定默认文件名   
		int index = path.lastIndexOf("/");
		//  前提:传入的path字符串以“\”表示目录分隔符    
		String fileName = path.substring(index + 1);
		//  写流文件到前端浏览器    
		ServletOutputStream out = res.getOutputStream();
		res.setHeader("Content-disposition", "attachment;filename=" + fileName);
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			bis = new BufferedInputStream(new FileInputStream(path));
			bos = new BufferedOutputStream(out);
			byte[] buff = new byte[2048];
			int bytesRead;
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
		} catch (IOException e) {
			throw e;
		} finally {
			if (bis != null) {
				bis.close();
			}
			if (bos != null) {
				bos.close();
			}
		}
	}
}


这些代码初看有些复杂,但是仔细研究一下,还是都能理解和看懂的,都是Java基础的输入输出流操作。还有就是路径操作了。

主要的还是路径问题我说一下,因为这个问题我比较印象深刻。一般来说,我们正常操作的话是不会遇到这个问题,那么我是个不正常的人,所以我进行了不正常操作,导致我对这一方面有了一定的深入了解。

Windows默认的文档路径是以反斜杠显示的:D:\快盘资料\安卓日记\Activity的详细讲解。所以在Eclipse中获取系统绝对路径的时候,也是反斜杠的,刚开始我不懂,以为路径就应该是这样的,我还特地把文档上传部分保存的path相对路径也改成了反斜杠。后来前辈告诉我,这样是不行的。反斜杠在Liunx系统中是不支持的,所以如果web项目部署到liunx的系统中的话,这样的代码就存在严重的问题。但是为什么windows会支持反斜杠呢,而且更强悍的是,windows还支持混乱斜杠,也就是正反斜杠它都能识别。这就是导致我一开始怎么也想不明白,为什么明明是反斜杠,而保存的path路径设置成正斜杠。那是因为如果在liunx中获取到的绝对路径就是正斜杠的了,后面的相对路径path就需要正斜杠的了,不然不支持的。

看看windows的混乱支持:

D:\ProgramExamples\Workspaces\Eclipse\app-oaShengRui\src\main\web\uploads/others/201207/d302121e8a534ed29747e60557fe7b87.htm

这样也是可以下载和访问的呀。

最后说一下Servlet的配置和使用方法:

web.xml中写如下配置

<servlet>
		<servlet-name>fileUpload</servlet-name>
		<servlet-class>cn.trymore.core.web.servlet.FileUploadServlet</servlet-class>
	</servlet>
	
	<servlet-mapping>
		<servlet-name>fileUpload</servlet-name>
		<url-pattern>/file-upload</url-pattern>
	</servlet-mapping>
	
	<servlet>
		<servlet-name>FileDownload</servlet-name>
		<servlet-class>cn.trymore.core.web.servlet.FileDownloadServlet</servlet-class>
	</servlet>
	
	<servlet-mapping>
		<servlet-name>FileDownload</servlet-name>
		<url-pattern>/file-download</url-pattern>
  	</servlet-mapping>

然后使用的话,file-upload直接用就可以了。download?path=?跟一个参数就可以了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值