用JSP+servlet实现文件的上传与下载

来源:互联网 发布:昂楷科技 知乎 编辑:程序博客网 时间:2024/05/22 15:54

现在看来使用JSP+Servlet实现文件的上传与下载已经是有些落后了,现在能很方便实现文件的上传与下载插件和工具有很多,常用的有SmartUpload插件、Struts2框架以及富文本编辑器等等。但是作为一个合格的程序员,我认为还是有必要了解一下使用JSP+Servlet最原始的读取文件流来实现文件的上传与下载。下面我简单讲下!

        要使用JSP通过表单实现文件的上传与下载,首先就必须要了解enctye这个属性,enctype 属性是规定在发送到服务器之前应该如何对表单数据进行编码。enctype常用的属性值有3个:第一个是application/x-www-form-urlencoded,这是默认的编码方式,它只处理表单域里的value属性值,采用这种编码方式的表单会将表单域的值处理成URL编码方式,第二种是multipart/form-data,这种编码方式的表单会以二进制流的方式来处理表单数据,同时,这种编码方式也会把文件域指定文件的内容封装到请求参数里,第三种就是text/plain,这种方式主要适合用于直接通过表单发送邮件的方式。

        我们要使用JSP实现文件的上传和下载,这里的enctype属性的属性值一定要选multipart/form-data,让表单提交的数据以二进制编码的方式提交,在接收此请求的Servlet中用二进制流来获取内容,就可以取得上传文件的内容,从而实现文件的上传。

下面写个小例子:

先贴出前台页面代码:

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <!DOCTYPE html >  
  2. <html>  
  3. <head>  
  4. <meta charset="UTF-8">  
  5. <title>使用JSP+Servlet实现文件的上传下载</title>  
  6. </head>  
  7. <script type="text/javascript" src="js/jquery-1.11.1.js"></script>  
  8. <body>  
  9.     <h2>使用JSP+Servlet实现文件的上传下载</h2>  
  10.     <form action="uploadServlet" method="post" enctype="multipart/form-data" >  
  11.             请选择文件:<input id="file" name="file" type="file" />  
  12.         <input type="submit" value="上传"  />${result}  
  13.         </form>  
  14.     下载:<a href="downloadServlet?filename=FileTest.txt">fileTest.txt</a> ${errorResult}   
  15. </body>  
  16. </html>  
             这里一定要注意,表单的method一定要使用post方式,其它的就很简单了,至于${result}这种语句是EL表达式。实现上传文件的UploadServlet的代码:
[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.dw.servlet;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7. import java.io.RandomAccessFile;  
  8. import javax.servlet.RequestDispatcher;  
  9. import javax.servlet.ServletException;  
  10. import javax.servlet.http.HttpServlet;  
  11. import javax.servlet.http.HttpServletRequest;  
  12. import javax.servlet.http.HttpServletResponse;  
  13.   
  14. public class UploadServlet extends HttpServlet {  
  15.     private static final long serialVersionUID = 1L;  
  16.     public UploadServlet() {  
  17.         super();  
  18.     }  
  19.   
  20.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  21.         doPost(request,response);  
  22.     }  
  23.   
  24.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  25.         request.setCharacterEncoding("utf-8");  
  26.         response.setCharacterEncoding("utf-8");  
  27.         response.setContentType("text/html;charset=utf-8");//更改响应字符流使用的编码,还能告知浏览器用什么编码进行显示  
  28.           
  29.         //从request中获取文本输入流信息  
  30.         InputStream fileSourceStream = request.getInputStream();  
  31.         String tempFileName = "F:/tempFile";  
  32.   
  33.         //设置临时文件,保存待上传的文本输入流  
  34.         File tempFile = new File(tempFileName);  
  35.           
  36.         //outputStram文件输出流指向这个tempFile  
  37.         FileOutputStream outputStream = new FileOutputStream(tempFile);  
  38.           
  39.         //读取文件流  
  40.         byte temp[] = new byte[1024];  
  41.         int n;  
  42.         while(( n = fileSourceStream.read(temp)) != -1){  
  43.             outputStream.write(temp, 0, n);  
  44.         }  
  45.         outputStream.close();  
  46.         fileSourceStream.close();  
  47.           
  48.         //获取上传文件的名称   
  49.         RandomAccessFile randomFile = new RandomAccessFile(tempFile,"r");  
  50.         randomFile.readLine();    
  51.         String str = randomFile.readLine();  
  52.         int start = str.lastIndexOf("=") + 2;  
  53.         int end = str.lastIndexOf("\"");  
  54.         String filename = str.substring(start, end);  
  55.           
  56.         //定位文件指针到文件头  
  57.         randomFile.seek(0);  
  58.         long startIndex = 0;  
  59.         int i = 1;  
  60.         //获取文件内容的开始位置  
  61.         while(( n = randomFile.readByte()) != -1 && i <=4){  
  62.             if(n == '\n'){  
  63.                 startIndex = randomFile.getFilePointer();  
  64.                 i ++;  
  65.             }  
  66.         }  
  67.         startIndex = startIndex -1; //这里一定要减1,因为前面多读了一个,这里很容易忽略  
  68.         //获取文件内容结束位置  
  69.         randomFile.seek(randomFile.length());  
  70.         long endIndex = randomFile.getFilePointer();  
  71.         int j = 1;  
  72.         while(endIndex >=0 && j<=2){  
  73.             endIndex--;  
  74.             randomFile.seek(endIndex);  
  75.             if(randomFile.readByte() == '\n'){  
  76.                 j++;  
  77.             }  
  78.         }  
  79.           
  80.         //设置保存上传文件的路径  
  81.         String realPath =  "F:/file";  
  82.         File fileupload = new File(realPath);  
  83.         if(!fileupload.exists()){  
  84.             fileupload.mkdir();  
  85.         }  
  86.         File saveFile = new File(realPath,filename);  
  87.         RandomAccessFile randomAccessFile = new RandomAccessFile(saveFile,"rw");  
  88.         //根据起止位置从临时文件中读取文件内容  
  89.         randomFile.seek(startIndex);  
  90.         while(startIndex < endIndex){  
  91.             randomAccessFile.write(randomFile.readByte());  
  92.             startIndex = randomFile.getFilePointer();  
  93.         }  
  94.         //关闭输入输出流并 删除临时文件  
  95.         randomAccessFile.close();  
  96.         randomFile.close();  
  97.         tempFile.delete();  
  98.           
  99.         request.setAttribute("result", "文件上传成功");  
  100.         RequestDispatcher dispatcher = request.getRequestDispatcher("index.jsp");  
  101.         dispatcher.forward(request, response);  
  102.     }  
  103.   
  104. }  
         在这个uploadServlet处理文件中,代码其实也很简单,就是处理接收到的数据流,具体步骤我在代码中注释的很清楚,一步一步来,很容易实现文件的上传,需要特别注意的是,上传的文件浏览器是使用什么的格式显示以及暂存我们的文件的。如下图:
      
        这个格式是固定不变的,不要忽略其中的空行,所以说截取文件名以及截取文件内容的时候,一定要注意截取的位置,完成到这里,我们就可以实现上传文件了!
      
点击浏览后选择testFile.txt文件,点击上传,会提示上传文件成功!会在指定的存储目录下看到这个文件。


下面再说说文件下载:
       文件下载原理分为三步:第一步需要通过HttpServletResponse.setContentType方法设置响应类型Content- Type头字段的值,让浏览器无法使用某种方式或激活某个程序来处理的MIME类型,我们这里用到的值为application/x- msdownload。第二步需要通过HttpServletResponse.setHeader方法设置响应头Content- Disposition的值为"attachment;filename=文件名"。第三步是读取文件进行下载,需要调用 HttpServletRespnse.getOutputStream方法返回的ServletOutputStream对象来向客服端写入附件文件的内容。

实现下载文件DownloadServlet的源代码:

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.dw.servlet;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7. import javax.servlet.RequestDispatcher;  
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.ServletOutputStream;  
  10. import javax.servlet.http.HttpServlet;  
  11. import javax.servlet.http.HttpServletRequest;  
  12. import javax.servlet.http.HttpServletResponse;  
  13. public class DownloadServlet extends HttpServlet {  
  14.     private static final long serialVersionUID = 1L;  
  15.     public DownloadServlet() {  
  16.         super();  
  17.     }  
  18.   
  19.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  20.         request.setCharacterEncoding("utf-8");  
  21.         response.setCharacterEncoding("utf-8");  
  22.           
  23.         //获取文件下载路径  
  24.         String path = "F:/file/";  
  25.         String filename = request.getParameter("filename");  
  26.         File file = new File(path + filename);  
  27.         if(file.exists()){  
  28.             //设置相应类型让浏览器知道用什么打开  用application/octet-stream也可以,看是什么浏览器  
  29.             response.setContentType("application/x-msdownload");  
  30.             //设置头信息  
  31.             response.setHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");  
  32.             InputStream inputStream = new FileInputStream(file);  
  33.             ServletOutputStream ouputStream = response.getOutputStream();  
  34.             byte b[] = new byte[1024];  
  35.             int n ;  
  36.             while((n = inputStream.read(b)) != -1){  
  37.                 ouputStream.write(b,0,n);  
  38.             }  
  39.             //关闭流  
  40.             ouputStream.close();  
  41.             inputStream.close();  
  42.         }else{  
  43.             request.setAttribute("errorResult", "文件不存在,下载失败!");  
  44.             RequestDispatcher dispatcher = request.getRequestDispatcher("index.jsp");  
  45.             dispatcher.forward(request, response);  
  46.         }  
  47.     }  
  48.   
  49.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  50.         doGet(request,response);  
  51.     }  
  52.   
  53. }  
当我们点击下载按钮是,会弹出下载框,如下图:

点击保存文件,就可以保存文件到任意的路径,这里保存到桌面,可以看出,文件并没有出现乱码,下载成功!


下面贴出web.xml文件:




好了,就先讲到这里!

下载源代码:https://github.com/zhanlong-dw/fileuploadanddownload
1 0