分享

java上传文件跟批量下载文件

 昵称21365845 2015-06-26

  最近的项目中涉及到文件的上传跟下载的问题,就自己所涉及到的方面做出如下表述。

  首先是文件上传部分,项目的要求是通用性较好,所以只需要传入目标路径即可。参数的传递通过Form表单传值,在目标路径下新建一个File类型的文件,然后通过流的方式将需要上传的文件写入新建的文件中。此方法适用于web开发过程中上传文档类的文件,如果你文件过大请研究ftp相关的知识,笔者所接触的ftp传文件限于C#中,这里不做表述。具体代码如下:

  1. 1 public void fileUpload(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  2. 2 {
  3. 3 String filePath = new String();
  4. 4 request.setCharacterEncoding("UTF-8");
  5. 5 response.setContentType("text/html; charset=GB2312");
  6. 6 try
  7. 7 {
  8. 8 DiskFileItemFactory factory = new DiskFileItemFactory();
  9. 9 //设置缓存中最大允许缓存为2M
  10. 10 factory.setSizeThreshold(2 * 1024 * 1024);
  11. 11 ServletFileUpload upload = new ServletFileUpload(factory);
  12. 12 //解决中文文件名为乱码的问题
  13. 13 upload.setHeaderEncoding("UTF-8");
  14. 14 List<FileItem> fileList = upload.parseRequest(request);
  15. 15 Iterator iter = fileList.iterator();
  16. 16 String newFileName = "";
  17. 17 while (iter.hasNext())
  18. 18 {
  19. 19 //获取文件
  20. 20 FileItem fileItem = (FileItem)iter.next();
  21. 21 //获取文件上传的路径
  22. 22 String typeName = fileItem.getFieldName();
  23. 23 if(("destPath").equals(typeName))
  24. 24 {
  25. 25 filePath = fileItem.getString("utf-8");
  26. 26 }
  27. 27 if(("filename").equals(typeName))
  28. 28 {
  29. 29 newFileName = fileItem.getString("utf-8");
  30. 30 }
  31. 31 String fileName = new String();
  32. 32 if (!fileItem.isFormField())
  33. 33 {
  34. 34 String name = fileItem.getName();
  35. 35 if(StringUtil.isNullOrEmpty(name))
  36. 36 {
  37. 37 continue;
  38. 38 }
  39. 39 fileName = name;
  40. 40 fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
  41. 41 File file = new File(filePath);
  42. 42 if(!file.exists())
  43. 43 {
  44. 44 file.mkdirs();
  45. 45 }
  46. 46 //向指定的路径写文件
  47. 47 if(newFileName.length()>0)
  48. 48 {
  49. 49 fileName = newFileName;
  50. 50 }
  51. 51 fileItem.write(new File(filePath, fileName));
  52. 52 }
  53. 53 }
  54. 54 }
  55. 55 catch (Exception ex)
  56. 56 {
  57. 57 throw new ServletException("上传文件失败!", ex);
  58. 58 }
  59. 59 }

  第二部分是关于文件批量下载的文档。根据客户的观点有上传就要下载的需求,一开始也做了相关的开发,结果发现下载时的文件全部存在服务器端,跟需求不一致。仔细推敲了下代码原来自己写的有问题,在客户端是选择文件的存储路径,然后将文件下载,其实只是实现了本地的迁移,并没有在把文件下载到客户端。后来的想法是把文件打包下载,用FileOutputStream,实现下载的问题,可是如果下载的文件中含有中文字符,就会出现乱码。不得已百度了下,原来是编码的问题,使用java自带的文件输出类不能解决压缩文件中文件名乱码的问题。解决方法:使用ant.jar包,创建压缩文件时,可以设置文件的编码格式,文件名乱码的问题就解决了。由于笔者在开发过程中数据库中有文件的路径,所以下列文件的文件路径的获取是查询得到。

  具体的解决代码如下:

  引用ant.jar包中的FileOutputStream类

  1. import org.apache.tools.zip.ZipEntry;
  2. import org.apache.tools.zip.ZipOutputStream;

  打包下载多个文件的思路就是在服务端创建一个新的压缩文件(zip格式),然后将下载的多个文件写入该压缩包中,然后以流的形式输出压缩文件写到客户端,实现下载功能。

  1. 1 public void downloadFiles(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  2. 2 {
  3. 3 request.setCharacterEncoding("UTF-8");
  4. 4 String docId = new String(request.getParameter("docId").getBytes("ISO-8859-1"), "UTF-8");
  5. 5 String downloadType = new String(request.getParameter("downloadType").getBytes("ISO-8859-1"), "UTF-8");
  6. 6
  7. 7 Document doc = null;
  8. 8 try
  9. 9 {
  10. 10 doc = getFilePath(docId);  //此方法获取文件的路径,这个不显示
  11. 11 }
  12. 12 catch (SQLException ex)
  13. 13 {
  14. 14 ex.printStackTrace();
  15. 15 }
  16. 16    
  17. 17 List<Element> elements = doc.getRootElement().elements();
  18. 18 List<File> files = new ArrayList<File>();
  19. 19 int index = 0;
  20. 20 long fileLength = 0;
  21. 21 for(Element ele : elements)
  22. 22 {
  23. 23 String filePath = FormatUtil.tryGetItemText(ele, "FILE_PATH", "") + FormatUtil.tryGetItemText(ele, "FILE_NAME", "");
  24. 24 File file = new File(filePath);
  25. 25 files.add(file);
  26. 26 fileLength += file.length();
  27. 27 index++;
  28. 28 }
  29. 29 String fileName = UUID.randomUUID().toString() + ".zip";
  30. 30 //在服务器端创建打包下载的临时文件
  31. 31 String outFilePath = "C:\\" + fileName;
  32. 32 File file = new File(outFilePath);
  33. 33 //文件输出流
  34. 34 FileOutputStream outStream = new FileOutputStream(file);
  35. 35 //压缩流
  36. 36 ZipOutputStream toClient = new ZipOutputStream(outStream);
  37. 37 toClient.setEncoding("gbk");
  38. 38 zipFile(files, toClient);
  39. 39 toClient.close();
  40. 40 outStream.close();
  41. 41 this.downloadZip(file, response);
  42. 42 }
  43. 43 /**
  44. 44 * 压缩文件列表中的文件
  45. 45 * @param files
  46. 46 * @param outputStream
  47. 47 * @throws IOException
  48. 48 */
  49. 49 public static void zipFile(List files, ZipOutputStream outputStream) throws IOException,ServletException
  50. 50 {
  51. 51 try
  52. 52 {
  53. 53 int size = files.size();
  54. 54 //压缩列表中的文件
  55. 55 for(int i = 0; i < size; i++)
  56. 56 {
  57. 57 File file = (File) files.get(i);
  58. 58 zipFile(file, outputStream);
  59. 59 }
  60. 60 }
  61. 61 catch(IOException e)
  62. 62 {
  63. 63 throw e;
  64. 64 }
  65. 65 }
  66. 66 /**
  67. 67 * 将文件写入到zip文件中
  68. 68 * @param inputFile
  69. 69 * @param outputstream
  70. 70 * @throws Exception
  71. 71 */
  72. 72 public static void zipFile(File inputFile, ZipOutputStream outputstream) throws IOException,ServletException
  73. 73 {
  74. 74 try{
  75. 75 if(inputFile.exists())
  76. 76 {
  77. 77 if(inputFile.isFile())
  78. 78 {
  79. 79 FileInputStream inStream = new FileInputStream(inputFile);
  80. 80 BufferedInputStream bInStream = new BufferedInputStream(inStream);
  81. 81 ZipEntry entry = new ZipEntry(inputFile.getName());
  82. 82 outputstream.putNextEntry(entry);
  83. 83
  84. 84 final int MAX_BYTE = 10 * 1024 *1024; //最大的流为10M
  85. 85 long streamTotal = 0; //接受流的容量
  86. 86 int streamNum = 0; //流需要分开的数量
  87. 87 int leaveByte = 0; //文件剩下的字符数
  88. 88 byte[] inOutbyte; //byte数组接受文件的数据
  89. 89
  90. 90 streamTotal = bInStream.available(); //通过available方法取得流的最大字符数
  91. 91 streamNum = (int)Math.floor(streamTotal / MAX_BYTE); //取得流文件需要分开的数量
  92. 92 leaveByte = (int)streamTotal % MAX_BYTE; //分开文件之后,剩余的数量
  93. 93
  94. 94 if (streamNum > 0)
  95. 95 {
  96. 96 for(int j = 0; j < streamNum; ++j)
  97. 97 {
  98. 98 inOutbyte = new byte[MAX_BYTE];
  99. 99 //读入流,保存在byte数组
  100. 100 bInStream.read(inOutbyte, 0, MAX_BYTE);
  101. 101 outputstream.write(inOutbyte, 0, MAX_BYTE); //写出流
  102. 102 }
  103. 103 }
  104. 104 //写出剩下的流数据
  105. 105 inOutbyte = new byte[leaveByte];
  106. 106 bInStream.read(inOutbyte, 0, leaveByte);
  107. 107 outputstream.write(inOutbyte);
  108. 108 outputstream.closeEntry(); //Closes the current ZIP entry and positions the stream for writing the next entry
  109. 109 bInStream.close(); //关闭
  110. 110 inStream.close();
  111. 111 }
  112. 112 }
  113. 113 else
  114. 114 {
  115. 115 throw new ServletException("文件不存在!");
  116. 116 }
  117. 117 }
  118. 118 catch(IOException e)
  119. 119 {
  120. 120 throw e;
  121. 121 }
  122. 122 }
  123. 123 /**
  124. 124 * 下载打包的文件
  125. 125 * @param file
  126. 126 * @param response
  127. 127 */
  128. 128 public void downloadZip(File file,HttpServletResponse response) {
  129. 129 try {
  130. 130 // 以流的形式下载文件。
  131. 131 BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file.getPath()));
  132. 132 byte[] buffer = new byte[fis.available()];
  133. 133 fis.read(buffer);
  134. 134 fis.close();
  135. 135 // 清空response
  136. 136 response.reset();
  137. 137
  138. 138 OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
  139. 139 response.setContentType("application/octet-stream");
  140. 140 response.setHeader("Content-Disposition", "attachment;filename=" + file.getName());
  141. 141 toClient.write(buffer);
  142. 142 toClient.flush();
  143. 143 toClient.close();
  144. 144 file.delete(); //将生成的服务器端文件删除
  145. 145 }
  146. 146 catch (IOException ex) {
  147. 147 ex.printStackTrace();
  148. 148 }
  149. 149 }

  单个文件的下载直接下载文件即可,使用java自带的FileOutputStream就能实现,可以从上面的批量下载中提取单个文件下载的方法。

  涉及到文件名称编码的问题,这里提供一个格式化中文字符串的方法。

  

  1. 1 public static String toUtf8String(String s){
  2. 2 StringBuffer sb = new StringBuffer();
  3. 3 for (int i = 0;i < s.length(); i++){
  4. 4 char c = s.charAt(i);
  5. 5 if (c >= 0 && c <= 255)
  6. 6 {
  7. 7 sb.append(c);
  8. 8 }
  9. 9 else{
  10. 10 byte[] b;
  11. 11 try
  12. 12 {
  13. 13 b = Character.toString(c).getBytes("utf-8");
  14. 14 }
  15. 15 catch (Exception ex) {
  16. 16 b = new byte[0];
  17. 17 }
  18. 18 for (int j = 0; j < b.length; j++) {
  19. 19 int k = b[j];
  20. 20 if (k < 0) k += 256;
  21. 21 sb.append("%" + Integer.toHexString(k).toUpperCase());
  22. 22 }
  23. 23 }
  24. 24 }
  25. 25 return sb.toString();
  26. 26 }

  

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约