• 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=='
    '){
    		    	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()=='
    '){
    		        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;
    	}
    	
    }


    
    
  • 相关阅读:
    类的继承
    垃圾回收GC
    网络层
    数据链路层
    TCP/IP协议分层模型
    OSI参考模型
    浏览器访问一个域名的过程
    Thread&ThreadLocal
    设计模式---单例模式
    内存泄漏和内存溢出
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3201336.html
Copyright © 2020-2023  润新知