基于Java文件输入输出流的文件上传下载功能实现
原理: 前端通过form表单的enctype属性,将数据传递方式修改为二进制”流“的形式,服务端(servlet)通过 getInputStream() 获取流信息, 运用java I/O 流的基础操作将流写入到一个服务端临时创建的文件temp中,然后再次利用文件基本操作,读取并截取临时文件内容,根据其中信息创建相应的文件,将读取出来的具体信息写入,下载时,根据提交的文件名称,找到服务器端相应的文件,然后根据输出流outStream输出到页面,同时将servlet的响应类型和响应头进行设置。
具体传输流程如下图:
流信息的部分为:
具体代码如下:
前端代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 <html> 2 <head> 3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 4 <title>Insert title here</title> 5 <script src="Js/jquery.js"></script> 6 </head> 7 <body> 8 <form action="FileUpServlet" method="post" enctype="multipart/form-data"> 9 <table> 10 <tr> 11 <td>请选择上传文件:</td><td><input id="myfile" name="myfile" type="file" value="" /></td> 12 <td><input type="submit" value="上传"></td> 13 </tr> 14 <tr><td>${info}</td></tr> 15 </table> 16 </form> 17 文件下载:<a href="FileLoadownServlet?filename=${filename}">${filename}</a> 18 </body> 19 </html>
上传servlet部分(核心)
1 @WebServlet("/FileUpServlet") 2 public class FileUpServlet extends HttpServlet { 3 private static final long serialVersionUID = 1L; 4 5 /** 6 * @see HttpServlet#HttpServlet() 7 */ 8 public FileUpServlet() { 9 super(); 10 // TODO Auto-generated constructor stub 11 } 12 13 /** 14 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) 15 */ 16 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 17 // TODO Auto-generated method stub 18 doPost(request, response); 19 } 20 21 /** 22 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) 23 */ 24 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 25 // TODO Auto-generated method stub 26 request.setCharacterEncoding("utf-8"); 27 InputStream filesource = request.getInputStream();//request获取流信息 28 String tempname = "D:/temp";//tempfile代表临时存放文件 29 File tempfile = new File(tempname);//创建临时文件 30 31 FileOutputStream outputStream = new FileOutputStream(tempfile);//输出流对象,指定输出指tempfile目录下 32 byte b[] = new byte[1024]; 33 int n; 34 while((n = filesource.read(b))!= -1)//从输出流中每次读取1024字节,直至读完 35 { 36 outputStream.write(b,0,n); 37 } 38 outputStream.close(); 39 filesource.close();//关闭输入输出流 40 41 42 /*以下为具体的文件操作,主要为解析临时产生的 temp文件 ,知识多为java输入输出流的内容!*/ 43 44 45 RandomAccessFile randomfile = new RandomAccessFile(tempfile, "r");//随机流,指定要读临时文件,只读 46 randomfile.readLine();//读取第一行,无效数据,不需要 47
String strs = randomfile.readLine();//读取第二行
byte t[] = strs.getBytes("iso-8859-1");
String str = new String(t,"utf-8");//读取乱码问题,根据不同的机器编码决定所填信息
48 int beginIndex = str.lastIndexOf("=")+2;//指定所需数据的开始位置 49 int endIndex = str.lastIndexOf("\"");//指定所需数据截至位置 50 String filename = str.substring(beginIndex,endIndex);//截取文件名 51 52 //重新定位文件指针,获取文件内容 53 randomfile.seek(0);//文件指针从头开始 54 long startext = 0; 55 int i = 1; 56 //文件内容开始位置 57 while((n=randomfile.readByte()) != -1&&i <= 4) 58 { 59 if(n=='\n') 60 { 61 startext = randomfile.getFilePointer(); 62 i++; 63 } 64 } 65 startext = randomfile.getFilePointer() - 1; 66 //获取文件内容 结束位置 67 randomfile.seek(randomfile.length()); 68 long endtext = randomfile.getFilePointer(); 69 int j = 1; 70 while(endtext >= 0 && j <= 2) 71 { 72 endtext--; 73 randomfile.seek(endtext); 74 if(randomfile.readByte()=='\n') 75 { 76 j++; 77 } 78 } 79 endtext = endtext-1; 80 81 //将临时文件保存至指定目录中 82 String realpath = getServletContext().getRealPath("/")+"images";//设置文件保存目录 83 System.out.println(realpath); 84 File fileupload = new File(realpath); 85 if(!fileupload.exists()) 86 { 87 fileupload.mkdir();//目录不存在则创建 88 } 89 File savefile = new File(realpath,filename); 90 RandomAccessFile randomAccessFile = new RandomAccessFile(savefile, "rw"); 91 randomfile.seek(startext); 92 while(startext<endtext){ 93 randomAccessFile.write(randomfile.readByte());//文件写入 94 startext = randomfile.getFilePointer(); 95 } 96 //关闭各种输入输出流 97 randomAccessFile.close(); 98 randomfile.close(); 99 tempfile.delete();//删除临时文件 100 101 102 SimpleDateFormat timed = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 103 Date nowdate = new Date(); 104 String time = timed.format(nowdate.getTime()); 105 request.setAttribute("info", time+" "+filename+"上传成功!"); 106 request.setAttribute("filename", filename); 107 request.getRequestDispatcher("/fildeOp.jsp").forward(request, response); 108 } 109 110 }
注意:使用随机流RondomAccesFile流的readLine()方法在读取含有非ASCLL字符的文件时(如含有汉字)会出现乱码问题,具体对应以上代码截取文件名代码内容,
解决方法具体为将readline读取来的信息转至byte格式,然后对其进行编码修改,再次转为String
1)读取
String strs = in.readLine();
(2)用 iso-8859-1 重新编码
byte b[] = strs.getBytes("iso-8859-1");
(3)使用当前机器的默认编码将字节数组转化为字符串
String content = new String(b);
如果当前机器默认编码是GB2312,那么,上面等价于:
String content = new String(b,"GB2312");
(有的是utf-8)
下载部分
1 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 2 // TODO Auto-generated method stub 3 String filename = request.getParameter("filename"); 4 String path = getServletContext().getRealPath("/")+"images/"; 5 File file = new File(path+filename);//找到文件 6 if(file.exists()) 7 { 8 response.setContentType("application/x-msdownload"); //设置响应类型,此处为下载类型 9 response.setHeader("Content-Disposition", "attachment;filename=\""+filename+"\"");//以附件的形式打开 10 InputStream inputStream = new FileInputStream(file); 11 ServletOutputStream outputStream = response.getOutputStream(); 12 byte b[] = new byte[1024]; 13 int n; 14 while((n = inputStream.read(b)) != -1) 15 { 16 outputStream.write(b,0,n); 17 } 18 outputStream.close(); 19 inputStream.close(); 20 }else{ 21 request.setAttribute("result", "文件不存在!下载失败!"); 22 request.getRequestDispatcher("/fildeOp.jsp").forward(request, response); 23 } 24 }
补充!!!!: 此种方法的基本原理并非真正意义上的传输本地的文件,而是伪造一个假象,即服务端通过上传流数据,服务端接收 一堆流数据,存放至临时文件中,然后以文件IO操作读取解析临时文件,获取其中的文件名,以此在服务端相应目录下创建新文件,File xxx = new File(),然后继续读取临时文件,将其中内容存至服务端新文件中,在服务端制作一个一摸一样的文件来完成文件上传这个操作。
基于SmartUpload组件的文件上传下载
文件上传源码:
1 @WebServlet("/SmartUploadServlet") 2 public class SmartUploadServlet extends HttpServlet { 3 4 public void doGet(HttpServletRequest req, HttpServletResponse resp) 5 throws ServletException, IOException { 6 doPost(req,resp); 7 } 8 9 public void doPost(HttpServletRequest req, HttpServletResponse resp) 10 throws ServletException, IOException { 11 //设置上传文件保存路径 12 String filePath = getServletContext().getRealPath("/") + "images"; 13 File file = new File(filePath); 14 if(!file.exists()){ 15 file.mkdir(); 16 } 17 18 SmartUpload su = new SmartUpload(); 19 //初始化对象 20 su.initialize(getServletConfig(), req, resp); 21 //设置上传文件大小 22 su.setMaxFileSize(1024*1024*10); 23 //设置所有文件的大小 24 su.setTotalMaxFileSize(1024*1024*100); 25 //设置允许上传文件类型 26 su.setAllowedFilesList("txt,jpg,gif"); 27 String result = "上传成功!"; 28 //设置禁止上传的文件类型 29 try { 30 su.setDeniedFilesList("rar,jsp,js"); 31 //上传文件 32 su.upload(); 33 34 int count = su.save(filePath); 35 System.out.println("上传成功" + count + "个文件!"); 36 } catch (Exception e) { 37 result = "上传失败!"; 38 e.printStackTrace(); 39 } 40 41 req.setAttribute("result", result); 42 req.getRequestDispatcher("formFile.html").forward(req, resp); 43 } 44 45 }
文件下载源码:
1 @WebServlet("/SmartDownloadServlet") 2 public class SmartDownloadServlet extends HttpServlet { 3 4 public void doGet(HttpServletRequest request, HttpServletResponse response) 5 throws ServletException, IOException { 6 doPost(request,response); 7 } 8 9 public void doPost(HttpServletRequest request, HttpServletResponse response) 10 throws ServletException, IOException { 11 12 String filename = request.getParameter("filename"); 13 14 SmartUpload su = new SmartUpload(); 15 su.initialize(getServletConfig(), request, response); 16 su.setContentDisposition(null); 17 try { 18 su.downloadFile("/images/"+ filename); 19 } catch (SmartUploadException e) { 20 e.printStackTrace(); 21 } 22 } 23 24 }