当前位置: 代码迷 >> Web前端 >> Servlet 兑现文件的上传与下载
  详细解决方案

Servlet 兑现文件的上传与下载

热度:167   发布时间:2013-07-20 11:07:48.0
Servlet 实现文件的上传与下载 .
这段时间尝试写了一个小web项目,其中涉及到文件上传与下载,虽然网上有很多成熟的框架供使用,但为了学习我还是选择了自己编写相关的代码。当中遇到了很多问题,所以在此这分享完整的上传与下载代码供大家借鉴。

首先是上传的Servlet代码

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.util.Random;

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

public class UpLoad extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	private static final Random RANDOM = new Random();		
	private String tempFileFolder;	//临时文件存放目录
	private String fileFolder;	//存文件的目录

	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//step 1 将上传文件流写入到临时文件
		File tempFile = getTempFile();
		writeToTempFile(request.getInputStream(), tempFile);
		
		//step 2从临时文件中取得上传文件流
		RandomAccessFile randomFile = new RandomAccessFile(tempFile, "r");
		
		//step 3取得文件名称
		String filename = getFileName(randomFile);
		
		//step 4检查存放文件的目录在不在
		checkFold();
		
		//step 5保存文件
		long fileSize = saveFile(randomFile, filename);
		
		//step 6关闭流对像,删除临时文件
		randomFile.close();
		tempFile.delete();
		
	}

	public void init() throws ServletException {
		//获取项目所在目录
		String contentPath = getServletContext().getRealPath("/");
		this.tempFileFolder = contentPath + "files/_tmp";
		this.fileFolder = contentPath+"files/_file";
	}
	
	
	/**
	 * 对字符串进行转码
	 * @param str
	 * @return 转码后的字符串
	 */
	private String codeString(String str) {
		String s = str;
		try {
			byte[] temp = s.getBytes("ISO-8859-1");
			s = new String(temp, "UTF-8");
			return s;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return s;
		}
	}
	
	/**
	 * 产生临时文件对象
	 * 会检查临时目录是否存在,如果不存在将创建目录
	 * @return 临时文件对象
	 * @throws IOException
	 */
	private File getTempFile()throws IOException{
		File tempFolder = new File(this.tempFileFolder);
		if (!tempFolder.exists()){
			tempFolder.mkdirs();
		}
		String tempFileName = this.tempFileFolder+File.separator+Math.abs(RANDOM.nextInt());
		File tempFile = new File(tempFileName);
		if (!tempFile.exists()){
			tempFile.createNewFile();
		}
		return tempFile;
	}
	
	/**
	 * 将上传的数据流存入临时文件
	 * @param fileSourcel 上传流
	 * @param tempFile	      临时文件
	 * @throws IOException
	 */
	private void writeToTempFile(InputStream fileSourcel,File tempFile)throws IOException{
		FileOutputStream outputStream = new FileOutputStream(tempFile);
		byte b[] = new byte[1000];
		int n ;
		while ((n=fileSourcel.read(b))!=-1){
		    outputStream.write(b,0,n);
		}
		outputStream.close();
		fileSourcel.close();
	}
	
	/**
	 * 从临时文件流中提取文件名称
	 * @param randomFile
	 * @return 解析的文件名称
	 * @throws IOException
	 */
	private String getFileName(RandomAccessFile randomFile)throws IOException{
		String _line;
		while((_line=randomFile.readLine())!=null && !_line.contains("form-data; name=\"upload\"")){
		}
		String filePath = _line;
		String filename = filePath.replace("Content-Disposition: form-data; name=\"upload\"; filename=\"", "").replace("\"","");
		
		filename=codeString(filename);
		randomFile.seek(0);
		return filename;
	}
	
	/**
	 * 获取上传文件的开始位置
	 * 开始位置会因为from 表单的参数不同而不同
	 * 如果from表单只上传文件是从第四行开始
	 * 本例from表单还有一个title的input , 所以从第八行开始。每多一个参数就加四行。
	 * @param randomFile
	 * @return 上传文件的开始位置
	 * @throws IOException
	 */
	private long getFileEnterPosition(RandomAccessFile randomFile)throws IOException{
		long  enterPosition = 0;
		int forth = 1;
		int n ;
		while((n=randomFile.readByte())!=-1&&(forth<=8)){
		    if(n=='\n'){
		    	enterPosition = randomFile.getFilePointer();
		        forth++;
		    }
		}
		return enterPosition;
	}
	
	/**
	 * 获取上传文件的结束位置
	 * 结束位置会因为文件类型不同,而不同
	 * 压缩包是倒数第二行后
	 * @param randomFile
	 * @return 文件的结束位置
	 * @throws IOException
	 */
	private long getFileEndPosition(RandomAccessFile randomFile)throws IOException{
		randomFile.seek(randomFile.length());
		long endPosition = randomFile.getFilePointer();
		int j = 1;
		while((endPosition>=0)&&(j<=2)){
		    endPosition--;
		    randomFile.seek(endPosition);
		    if(randomFile.readByte()=='\n'){
		        j++;
		    }
		}
		return endPosition;
	}
	
	/**
	 * 检查要保存文件的文件夹是否存在
	 */
	private void checkFold(){
		File file = new File(this.fileFolder);
		if (!file.exists()){
			file.mkdirs();
		}
	}
	
	/**
	 * 将临时文件解析后存放到指定的文件存放目录
	 * @param randomFile
	 * @param forthEnterPosition
	 * @param filename
	 * @return fileSize
	 * @throws IOException
	 */
	private long saveFile(RandomAccessFile randomFile,String filename)throws IOException{
		File saveFile = new File(this.fileFolder,filename);
		RandomAccessFile randomAccessFile = new RandomAccessFile(saveFile,"rw");
		
		long forthEnterPosition = getFileEnterPosition(randomFile);
		long endPosition = getFileEndPosition(randomFile);
		//从上传文件数据的开始位置到结束位置,把数据写入到要保存的文件中
		randomFile.seek(forthEnterPosition);
		long startPoint = randomFile.getFilePointer();
		while(startPoint<endPosition){
		    randomAccessFile.write(randomFile.readByte());
		    startPoint = randomFile.getFilePointer();
		}
		long fileSize = randomAccessFile.length();
		randomAccessFile.close();
		return fileSize;
	}
}

接着是下载的Servlet代码
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;

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

public class Download extends HttpServlet {

	private static final long serialVersionUID = 1L;
	private static final String FILEDIR="files/_file";
	private String fileFolder;	//存文件的目录
	
	public Download() {
		super();
	}

	
	public void destroy() {
		super.destroy(); 
		// Put your code here
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
			this.doPost(request, response);
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
//		request.setCharacterEncoding("UTF-8");
		try{
			String fileName = request.getParameter("name");
			OutputStream outputStream = response.getOutputStream();
			//输出文件用的字节数组,每次向输出流发送600个字节
			byte b[] = new byte[600];
			
			File fileload = new File(this.fileFolder,fileName);
			
			fileName=encodeFileName(request,fileName);
			//客服端使用保存文件的对话框
			response.setHeader("Content-disposition", "attachment;filename="+fileName);
			//通知客户文件的长度
			long fileLength = fileload.length();
			String length = String.valueOf(fileLength);
			response.setHeader("Content_length", length);
			//读取文件,并发送给客服端下载
			FileInputStream inputStream = new FileInputStream(fileload);
			int n = 0;
			while((n=inputStream.read(b))!=-1){
			    outputStream.write(b,0,n);
			}
		}catch(FileNotFoundException fnfe){
			fnfe.printStackTrace();
			try{
				PrintWriter out = response.getWriter();
				out.println("下载的文件不存在");
				out.flush();
				out.close();
			}catch(IOException ie){
				ie.printStackTrace();
			}
		}catch(IOException ie){
			ie.printStackTrace();
			try{
				PrintWriter out = response.getWriter();
				out.println("下载存在问题");
				out.flush();
				out.close();
			}catch(IOException iex){
				iex.printStackTrace();
			}
		}
	}

	/**
	 * Initialization of the servlet. <br>
	 *
	 * @throws ServletException if an error occurs
	 */
	public void init() throws ServletException {
		this.fileFolder = getServletContext().getRealPath("/")+"files/_file";
	}
	
	private String encodeFileName(HttpServletRequest request,String fileName){
		try{
			//IE
			if (request.getHeader("User-Agent").toUpperCase().indexOf("MSIE") >0){
				fileName=URLEncoder.encode(fileName,"UTF-8");
			}else{
				fileName = new String(fileName.getBytes("UTF-8"),"ISO8859-1");
			}
		}catch(Exception ex){
			ex.printStackTrace();
		}
		return fileName;
	}
	
}
  相关解决方案