File 文件操作类 大全

  File  文件操作类  大全

许多人都会对文件操作感到很难  我也是  但是一个好的项目中必定会涉及到文件操作的

文件的复制 粘贴  等等等

 

公司大佬写了 一个文件操作的工具类 感觉还是棒棒的啦  

 

代码如下 :

  1 /**
  2  * Copyright &copy; 2012-2016 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
  3  */
  4 package com.thinkgem.jeesite.common.utils;
  5 
  6 import java.io.BufferedOutputStream;
  7 import java.io.File;
  8 import java.io.FileInputStream;
  9 import java.io.FileOutputStream;
 10 import java.io.IOException;
 11 import java.io.InputStream;
 12 import java.io.OutputStream;
 13 import java.io.RandomAccessFile;
 14 import java.util.Enumeration;
 15 import java.util.List;
 16 
 17 import javax.servlet.http.HttpServletRequest;
 18 import javax.servlet.http.HttpServletResponse;
 19 
 20 import org.apache.tools.zip.ZipEntry;
 21 import org.apache.tools.zip.ZipFile;
 22 import org.apache.tools.zip.ZipOutputStream;
 23 import org.slf4j.Logger;
 24 import org.slf4j.LoggerFactory;
 25 
 26 import com.google.common.collect.Lists;
 27 
 28 /**
 29  * 文件操作工具类
 30  * 实现文件的创建、删除、复制、压缩、解压以及目录的创建、删除、复制、压缩解压等功能
 31  * @author ThinkGem
 32  * @version 2015-3-16
 33  */
 34 public class FileUtils extends org.apache.commons.io.FileUtils {
 35     
 36     private static Logger logger = LoggerFactory.getLogger(FileUtils.class);
 37 
 38     /**
 39      * 复制单个文件,如果目标文件存在,则不覆盖
 40      * @param srcFileName 待复制的文件名
 41      * @param descFileName 目标文件名
 42      * @return 如果复制成功,则返回true,否则返回false
 43      */
 44     public static boolean copyFile(String srcFileName, String descFileName) {
 45         return FileUtils.copyFileCover(srcFileName, descFileName, false);
 46     }
 47 
 48     /**
 49      * 复制单个文件
 50      * @param srcFileName 待复制的文件名
 51      * @param descFileName 目标文件名
 52      * @param coverlay 如果目标文件已存在,是否覆盖
 53      * @return 如果复制成功,则返回true,否则返回false
 54      */
 55     public static boolean copyFileCover(String srcFileName,
 56             String descFileName, boolean coverlay) {
 57         File srcFile = new File(srcFileName);
 58         // 判断源文件是否存在
 59         if (!srcFile.exists()) {
 60             logger.debug("复制文件失败,源文件 " + srcFileName + " 不存在!");
 61             return false;
 62         }
 63         // 判断源文件是否是合法的文件
 64         else if (!srcFile.isFile()) {
 65             logger.debug("复制文件失败," + srcFileName + " 不是一个文件!");
 66             return false;
 67         }
 68         File descFile = new File(descFileName);
 69         // 判断目标文件是否存在
 70         if (descFile.exists()) {
 71             // 如果目标文件存在,并且允许覆盖
 72             if (coverlay) {
 73                 logger.debug("目标文件已存在,准备删除!");
 74                 if (!FileUtils.delFile(descFileName)) {
 75                     logger.debug("删除目标文件 " + descFileName + " 失败!");
 76                     return false;
 77                 }
 78             } else {
 79                 logger.debug("复制文件失败,目标文件 " + descFileName + " 已存在!");
 80                 return false;
 81             }
 82         } else {
 83             if (!descFile.getParentFile().exists()) {
 84                 // 如果目标文件所在的目录不存在,则创建目录
 85                 logger.debug("目标文件所在的目录不存在,创建目录!");
 86                 // 创建目标文件所在的目录
 87                 if (!descFile.getParentFile().mkdirs()) {
 88                     logger.debug("创建目标文件所在的目录失败!");
 89                     return false;
 90                 }
 91             }
 92         }
 93 
 94         // 准备复制文件
 95         // 读取的位数
 96         int readByte = 0;
 97         InputStream ins = null;
 98         OutputStream outs = null;
 99         try {
100             // 打开源文件
101             ins = new FileInputStream(srcFile);
102             // 打开目标文件的输出流
103             outs = new FileOutputStream(descFile);
104             byte[] buf = new byte[1024];
105             // 一次读取1024个字节,当readByte为-1时表示文件已经读取完毕
106             while ((readByte = ins.read(buf)) != -1) {
107                 // 将读取的字节流写入到输出流
108                 outs.write(buf, 0, readByte);
109             }
110             logger.debug("复制单个文件 " + srcFileName + " 到" + descFileName
111                     + "成功!");
112             return true;
113         } catch (Exception e) {
114             logger.debug("复制文件失败:" + e.getMessage());
115             return false;
116         } finally {
117             // 关闭输入输出流,首先关闭输出流,然后再关闭输入流
118             if (outs != null) {
119                 try {
120                     outs.close();
121                 } catch (IOException oute) {
122                     oute.printStackTrace();
123                 }
124             }
125             if (ins != null) {
126                 try {
127                     ins.close();
128                 } catch (IOException ine) {
129                     ine.printStackTrace();
130                 }
131             }
132         }
133     }
134 
135     /**
136      * 复制整个目录的内容,如果目标目录存在,则不覆盖
137      * @param srcDirName 源目录名
138      * @param descDirName 目标目录名
139      * @return 如果复制成功返回true,否则返回false
140      */
141     public static boolean copyDirectory(String srcDirName, String descDirName) {
142         return FileUtils.copyDirectoryCover(srcDirName, descDirName,
143                 false);
144     }
145 
146     /**
147      * 复制整个目录的内容 
148      * @param srcDirName 源目录名
149      * @param descDirName 目标目录名
150      * @param coverlay 如果目标目录存在,是否覆盖
151      * @return 如果复制成功返回true,否则返回false
152      */
153     public static boolean copyDirectoryCover(String srcDirName,
154             String descDirName, boolean coverlay) {
155         File srcDir = new File(srcDirName);
156         // 判断源目录是否存在
157         if (!srcDir.exists()) {
158             logger.debug("复制目录失败,源目录 " + srcDirName + " 不存在!");
159             return false;
160         }
161         // 判断源目录是否是目录
162         else if (!srcDir.isDirectory()) {
163             logger.debug("复制目录失败," + srcDirName + " 不是一个目录!");
164             return false;
165         }
166         // 如果目标文件夹名不以文件分隔符结尾,自动添加文件分隔符
167         String descDirNames = descDirName;
168         if (!descDirNames.endsWith(File.separator)) {
169             descDirNames = descDirNames + File.separator;
170         }
171         File descDir = new File(descDirNames);
172         // 如果目标文件夹存在
173         if (descDir.exists()) {
174             if (coverlay) {
175                 // 允许覆盖目标目录
176                 logger.debug("目标目录已存在,准备删除!");
177                 if (!FileUtils.delFile(descDirNames)) {
178                     logger.debug("删除目录 " + descDirNames + " 失败!");
179                     return false;
180                 }
181             } else {
182                 logger.debug("目标目录复制失败,目标目录 " + descDirNames + " 已存在!");
183                 return false;
184             }
185         } else {
186             // 创建目标目录
187             logger.debug("目标目录不存在,准备创建!");
188             if (!descDir.mkdirs()) {
189                 logger.debug("创建目标目录失败!");
190                 return false;
191             }
192 
193         }
194 
195         boolean flag = true;
196         // 列出源目录下的所有文件名和子目录名
197         File[] files = srcDir.listFiles();
198         for (int i = 0; i < files.length; i++) {
199             // 如果是一个单个文件,则直接复制
200             if (files[i].isFile()) {
201                 flag = FileUtils.copyFile(files[i].getAbsolutePath(),
202                         descDirName + files[i].getName());
203                 // 如果拷贝文件失败,则退出循环
204                 if (!flag) {
205                     break;
206                 }
207             }
208             // 如果是子目录,则继续复制目录
209             if (files[i].isDirectory()) {
210                 flag = FileUtils.copyDirectory(files[i]
211                         .getAbsolutePath(), descDirName + files[i].getName());
212                 // 如果拷贝目录失败,则退出循环
213                 if (!flag) {
214                     break;
215                 }
216             }
217         }
218 
219         if (!flag) {
220             logger.debug("复制目录 " + srcDirName + " 到 " + descDirName + " 失败!");
221             return false;
222         }
223         logger.debug("复制目录 " + srcDirName + " 到 " + descDirName + " 成功!");
224         return true;
225 
226     }
227 
228     /**
229      * 
230      * 删除文件,可以删除单个文件或文件夹
231      * 
232      * @param fileName 被删除的文件名
233      * @return 如果删除成功,则返回true,否是返回false
234      */
235     public static boolean delFile(String fileName) {
236          File file = new File(fileName);
237         if (!file.exists()) {
238             logger.debug(fileName + " 文件不存在!");
239             return true;
240         } else {
241             if (file.isFile()) {
242                 return FileUtils.deleteFile(fileName);
243             } else {
244                 return FileUtils.deleteDirectory(fileName);
245             }
246         }
247     }
248 
249     /**
250      * 
251      * 删除单个文件
252      * 
253      * @param fileName 被删除的文件名
254      * @return 如果删除成功,则返回true,否则返回false
255      */
256     public static boolean deleteFile(String fileName) {
257         File file = new File(fileName);
258         if (file.exists() && file.isFile()) {
259             if (file.delete()) {
260                 logger.debug("删除文件 " + fileName + " 成功!");
261                 return true;
262             } else {
263                 logger.debug("删除文件 " + fileName + " 失败!");
264                 return false;
265             }
266         } else {
267             logger.debug(fileName + " 文件不存在!");
268             return true;
269         }
270     }
271 
272     /**
273      * 
274      * 删除目录及目录下的文件
275      * 
276      * @param dirName 被删除的目录所在的文件路径
277      * @return 如果目录删除成功,则返回true,否则返回false
278      */
279     public static boolean deleteDirectory(String dirName) {
280         String dirNames = dirName;
281         if (!dirNames.endsWith(File.separator)) {
282             dirNames = dirNames + File.separator;
283         }
284         File dirFile = new File(dirNames);
285         if (!dirFile.exists() || !dirFile.isDirectory()) {
286             logger.debug(dirNames + " 目录不存在!");
287             return true;
288         }
289         boolean flag = true;
290         // 列出全部文件及子目录
291         File[] files = dirFile.listFiles();
292         for (int i = 0; i < files.length; i++) {
293             // 删除子文件
294             if (files[i].isFile()) {
295                 flag = FileUtils.deleteFile(files[i].getAbsolutePath());
296                 // 如果删除文件失败,则退出循环
297                 if (!flag) {
298                     break;
299                 }
300             }
301             // 删除子目录
302             else if (files[i].isDirectory()) {
303                 flag = FileUtils.deleteDirectory(files[i]
304                         .getAbsolutePath());
305                 // 如果删除子目录失败,则退出循环
306                 if (!flag) {
307                     break;
308                 }
309             }
310         }
311 
312         if (!flag) {
313             logger.debug("删除目录失败!");
314             return false;
315         }
316         // 删除当前目录
317         if (dirFile.delete()) {
318             logger.debug("删除目录 " + dirName + " 成功!");
319             return true;
320         } else {
321             logger.debug("删除目录 " + dirName + " 失败!");
322             return false;
323         }
324 
325     }
326 
327     /**
328      * 创建单个文件
329      * @param descFileName 文件名,包含路径
330      * @return 如果创建成功,则返回true,否则返回false
331      */
332     public static boolean createFile(String descFileName) {
333         File file = new File(descFileName);
334         if (file.exists()) {
335             logger.debug("文件 " + descFileName + " 已存在!");
336             return false;
337         }
338         if (descFileName.endsWith(File.separator)) {
339             logger.debug(descFileName + " 为目录,不能创建目录!");
340             return false;
341         }
342         if (!file.getParentFile().exists()) {
343             // 如果文件所在的目录不存在,则创建目录
344             if (!file.getParentFile().mkdirs()) {
345                 logger.debug("创建文件所在的目录失败!");
346                 return false;
347             }
348         }
349 
350         // 创建文件
351         try {
352             if (file.createNewFile()) {
353                 logger.debug(descFileName + " 文件创建成功!");
354                 return true;
355             } else {
356                 logger.debug(descFileName + " 文件创建失败!");
357                 return false;
358             }
359         } catch (Exception e) {
360             e.printStackTrace();
361             logger.debug(descFileName + " 文件创建失败!");
362             return false;
363         }
364 
365     }
366 
367     /**
368      * 创建目录
369      * @param descDirName 目录名,包含路径
370      * @return 如果创建成功,则返回true,否则返回false
371      */
372     public static boolean createDirectory(String descDirName) {
373         String descDirNames = descDirName;
374         if (!descDirNames.endsWith(File.separator)) {
375             descDirNames = descDirNames + File.separator;
376         }
377         File descDir = new File(descDirNames);
378         if (descDir.exists()) {
379             logger.debug("目录 " + descDirNames + " 已存在!");
380             return false;
381         }
382         // 创建目录
383         if (descDir.mkdirs()) {
384             logger.debug("目录 " + descDirNames + " 创建成功!");
385             return true;
386         } else {
387             logger.debug("目录 " + descDirNames + " 创建失败!");
388             return false;
389         }
390 
391     }
392 
393     /**
394      * 写入文件
395      * @param file 要写入的文件
396      */
397     public static void writeToFile(String fileName, String content, boolean append) {
398         try {
399             FileUtils.write(new File(fileName), content, "utf-8", append);
400             logger.debug("文件 " + fileName + " 写入成功!");
401         } catch (IOException e) {
402             logger.debug("文件 " + fileName + " 写入失败! " + e.getMessage());
403         }
404     }
405 
406     /**
407      * 写入文件
408      * @param file 要写入的文件
409      */
410     public static void writeToFile(String fileName, String content, String encoding, boolean append) {
411         try {
412             FileUtils.write(new File(fileName), content, encoding, append);
413             logger.debug("文件 " + fileName + " 写入成功!");
414         } catch (IOException e) {
415             logger.debug("文件 " + fileName + " 写入失败! " + e.getMessage());
416         }
417     }
418     
419     /**
420      * 压缩文件或目录
421      * @param srcDirName 压缩的根目录
422      * @param fileName 根目录下的待压缩的文件名或文件夹名,其中*或""表示跟目录下的全部文件
423      * @param descFileName 目标zip文件
424      */
425     public static void zipFiles(String srcDirName, String fileName,
426             String descFileName) {
427         // 判断目录是否存在
428         if (srcDirName == null) {
429             logger.debug("文件压缩失败,目录 " + srcDirName + " 不存在!");
430             return;
431         }
432         File fileDir = new File(srcDirName);
433         if (!fileDir.exists() || !fileDir.isDirectory()) {
434             logger.debug("文件压缩失败,目录 " + srcDirName + " 不存在!");
435             return;
436         }
437         String dirPath = fileDir.getAbsolutePath();
438         File descFile = new File(descFileName);
439         try {
440             ZipOutputStream zouts = new ZipOutputStream(new FileOutputStream(
441                     descFile));
442             if ("*".equals(fileName) || "".equals(fileName)) {
443                 FileUtils.zipDirectoryToZipFile(dirPath, fileDir, zouts);
444             } else {
445                 File file = new File(fileDir, fileName);
446                 if (file.isFile()) {
447                     FileUtils.zipFilesToZipFile(dirPath, file, zouts);
448                 } else {
449                     FileUtils
450                             .zipDirectoryToZipFile(dirPath, file, zouts);
451                 }
452             }
453             zouts.close();
454             logger.debug(descFileName + " 文件压缩成功!");
455         } catch (Exception e) {
456             logger.debug("文件压缩失败:" + e.getMessage());
457             e.printStackTrace();
458         }
459 
460     }
461 
462     /**
463      * 解压缩ZIP文件,将ZIP文件里的内容解压到descFileName目录下
464      * @param zipFileName 需要解压的ZIP文件
465      * @param descFileName 目标文件
466      */
467     public static boolean unZipFiles(String zipFileName, String descFileName) {
468         String descFileNames = descFileName;
469         if (!descFileNames.endsWith(File.separator)) {
470             descFileNames = descFileNames + File.separator;
471         }        
472         try {
473             // 根据ZIP文件创建ZipFile对象
474             ZipFile zipFile = new ZipFile(zipFileName);
475             ZipEntry entry = null;
476             String entryName = null;
477             String descFileDir = null;
478             byte[] buf = new byte[4096];
479             int readByte = 0;
480             // 获取ZIP文件里所有的entry
481             @SuppressWarnings("rawtypes")
482             Enumeration enums = zipFile.getEntries();
483             // 遍历所有entry
484             while (enums.hasMoreElements()) {
485                 entry = (ZipEntry) enums.nextElement();
486                 // 获得entry的名字
487                 entryName = entry.getName();
488                 descFileDir = descFileNames + entryName;
489                 if (entry.isDirectory()) {
490                     // 如果entry是一个目录,则创建目录
491                     new File(descFileDir).mkdirs();
492                     continue;
493                 } else {
494                     // 如果entry是一个文件,则创建父目录
495                     new File(descFileDir).getParentFile().mkdirs();
496                 }
497                 File file = new File(descFileDir);
498                 // 打开文件输出流
499                 OutputStream os = new FileOutputStream(file);
500                 // 从ZipFile对象中打开entry的输入流
501                 InputStream is = zipFile.getInputStream(entry);
502                 while ((readByte = is.read(buf)) != -1) {
503                     os.write(buf, 0, readByte);
504                 }
505                 os.close();
506                 is.close();
507             }
508             zipFile.close();
509             logger.debug("文件解压成功!");
510             return true;
511         } catch (Exception e) {
512             logger.debug("文件解压失败:" + e.getMessage());
513             return false;
514         }
515     }
516 
517     /**
518      * 将目录压缩到ZIP输出流
519      * @param dirPath 目录路径
520      * @param fileDir 文件信息
521      * @param zouts 输出流
522      */
523     public static void zipDirectoryToZipFile(String dirPath, File fileDir, ZipOutputStream zouts) {
524         if (fileDir.isDirectory()) {
525             File[] files = fileDir.listFiles();
526             // 空的文件夹
527             if (files.length == 0) {
528                 // 目录信息
529                 ZipEntry entry = new ZipEntry(getEntryName(dirPath, fileDir));
530                 try {
531                     zouts.putNextEntry(entry);
532                     zouts.closeEntry();
533                 } catch (Exception e) {
534                     e.printStackTrace();
535                 }
536                 return;
537             }
538 
539             for (int i = 0; i < files.length; i++) {
540                 if (files[i].isFile()) {
541                     // 如果是文件,则调用文件压缩方法
542                     FileUtils
543                             .zipFilesToZipFile(dirPath, files[i], zouts);
544                 } else {
545                     // 如果是目录,则递归调用
546                     FileUtils.zipDirectoryToZipFile(dirPath, files[i],
547                             zouts);
548                 }
549             }
550         }
551     }
552 
553     /**
554      * 将文件压缩到ZIP输出流
555      * @param dirPath 目录路径
556      * @param file 文件
557      * @param zouts 输出流
558      */
559     public static void zipFilesToZipFile(String dirPath, File file, ZipOutputStream zouts) {
560         FileInputStream fin = null;
561         ZipEntry entry = null;
562         // 创建复制缓冲区
563         byte[] buf = new byte[4096];
564         int readByte = 0;
565         if (file.isFile()) {
566             try {
567                 // 创建一个文件输入流
568                 fin = new FileInputStream(file);
569                 // 创建一个ZipEntry
570                 entry = new ZipEntry(getEntryName(dirPath, file));
571                 // 存储信息到压缩文件
572                 zouts.putNextEntry(entry);
573                 // 复制字节到压缩文件
574                 while ((readByte = fin.read(buf)) != -1) {
575                     zouts.write(buf, 0, readByte);
576                 }
577                 zouts.closeEntry();
578                 fin.close();
579                 System.out
580                         .println("添加文件 " + file.getAbsolutePath() + " 到zip文件中!");
581             } catch (Exception e) {
582                 e.printStackTrace();
583             }
584         }
585     }
586 
587     /**
588      * 获取待压缩文件在ZIP文件中entry的名字,即相对于跟目录的相对路径名
589      * @param dirPat 目录名
590      * @param file entry文件名
591      * @return
592      */
593     private static String getEntryName(String dirPath, File file) {
594         String dirPaths = dirPath;
595         if (!dirPaths.endsWith(File.separator)) {
596             dirPaths = dirPaths + File.separator;
597         }
598         String filePath = file.getAbsolutePath();
599         // 对于目录,必须在entry名字后面加上"/",表示它将以目录项存储
600         if (file.isDirectory()) {
601             filePath += "/";
602         }
603         int index = filePath.indexOf(dirPaths);
604 
605         return filePath.substring(index + dirPaths.length());
606     }
607 
608     /**
609      * 根据“文件名的后缀”获取文件内容类型(而非根据File.getContentType()读取的文件类型)
610      * @param returnFileName 带验证的文件名
611      * @return 返回文件类型
612      */
613     public static String getContentType(String returnFileName) {
614         String contentType = "application/octet-stream";
615         if (returnFileName.lastIndexOf(".") < 0)
616             return contentType;
617         returnFileName = returnFileName.toLowerCase();
618         returnFileName = returnFileName.substring(returnFileName.lastIndexOf(".") + 1);
619         if (returnFileName.equals("html") || returnFileName.equals("htm") || returnFileName.equals("shtml")) {
620             contentType = "text/html";
621         } else if (returnFileName.equals("apk")) {
622             contentType = "application/vnd.android.package-archive";
623         } else if (returnFileName.equals("sis")) {
624             contentType = "application/vnd.symbian.install";
625         } else if (returnFileName.equals("sisx")) {
626             contentType = "application/vnd.symbian.install";
627         } else if (returnFileName.equals("exe")) {
628             contentType = "application/x-msdownload";
629         } else if (returnFileName.equals("msi")) {
630             contentType = "application/x-msdownload";
631         } else if (returnFileName.equals("css")) {
632             contentType = "text/css";
633         } else if (returnFileName.equals("xml")) {
634             contentType = "text/xml";
635         } else if (returnFileName.equals("gif")) {
636             contentType = "image/gif";
637         } else if (returnFileName.equals("jpeg") || returnFileName.equals("jpg")) {
638             contentType = "image/jpeg";
639         } else if (returnFileName.equals("js")) {
640             contentType = "application/x-javascript";
641         } else if (returnFileName.equals("atom")) {
642             contentType = "application/atom+xml";
643         } else if (returnFileName.equals("rss")) {
644             contentType = "application/rss+xml";
645         } else if (returnFileName.equals("mml")) {
646             contentType = "text/mathml";
647         } else if (returnFileName.equals("txt")) {
648             contentType = "text/plain";
649         } else if (returnFileName.equals("jad")) {
650             contentType = "text/vnd.sun.j2me.app-descriptor";
651         } else if (returnFileName.equals("wml")) {
652             contentType = "text/vnd.wap.wml";
653         } else if (returnFileName.equals("htc")) {
654             contentType = "text/x-component";
655         } else if (returnFileName.equals("png")) {
656             contentType = "image/png";
657         } else if (returnFileName.equals("tif") || returnFileName.equals("tiff")) {
658             contentType = "image/tiff";
659         } else if (returnFileName.equals("wbmp")) {
660             contentType = "image/vnd.wap.wbmp";
661         } else if (returnFileName.equals("ico")) {
662             contentType = "image/x-icon";
663         } else if (returnFileName.equals("jng")) {
664             contentType = "image/x-jng";
665         } else if (returnFileName.equals("bmp")) {
666             contentType = "image/x-ms-bmp";
667         } else if (returnFileName.equals("svg")) {
668             contentType = "image/svg+xml";
669         } else if (returnFileName.equals("jar") || returnFileName.equals("var") 
670                 || returnFileName.equals("ear")) {
671             contentType = "application/java-archive";
672         } else if (returnFileName.equals("doc")) {
673             contentType = "application/msword";
674         } else if (returnFileName.equals("pdf")) {
675             contentType = "application/pdf";
676         } else if (returnFileName.equals("rtf")) {
677             contentType = "application/rtf";
678         } else if (returnFileName.equals("xls")) {
679             contentType = "application/vnd.ms-excel";
680         } else if (returnFileName.equals("ppt")) {
681             contentType = "application/vnd.ms-powerpoint";
682         } else if (returnFileName.equals("7z")) {
683             contentType = "application/x-7z-compressed";
684         } else if (returnFileName.equals("rar")) {
685             contentType = "application/x-rar-compressed";
686         } else if (returnFileName.equals("swf")) {
687             contentType = "application/x-shockwave-flash";
688         } else if (returnFileName.equals("rpm")) {
689             contentType = "application/x-redhat-package-manager";
690         } else if (returnFileName.equals("der") || returnFileName.equals("pem")
691                 || returnFileName.equals("crt")) {
692             contentType = "application/x-x509-ca-cert";
693         } else if (returnFileName.equals("xhtml")) {
694             contentType = "application/xhtml+xml";
695         } else if (returnFileName.equals("zip")) {
696             contentType = "application/zip";
697         } else if (returnFileName.equals("mid") || returnFileName.equals("midi") 
698                 || returnFileName.equals("kar")) {
699             contentType = "audio/midi";
700         } else if (returnFileName.equals("mp3")) {
701             contentType = "audio/mpeg";
702         } else if (returnFileName.equals("ogg")) {
703             contentType = "audio/ogg";
704         } else if (returnFileName.equals("m4a")) {
705             contentType = "audio/x-m4a";
706         } else if (returnFileName.equals("ra")) {
707             contentType = "audio/x-realaudio";
708         } else if (returnFileName.equals("3gpp")
709                 || returnFileName.equals("3gp")) {
710             contentType = "video/3gpp";
711         } else if (returnFileName.equals("mp4")) {
712             contentType = "video/mp4";
713         } else if (returnFileName.equals("mpeg")
714                 || returnFileName.equals("mpg")) {
715             contentType = "video/mpeg";
716         } else if (returnFileName.equals("mov")) {
717             contentType = "video/quicktime";
718         } else if (returnFileName.equals("flv")) {
719             contentType = "video/x-flv";
720         } else if (returnFileName.equals("m4v")) {
721             contentType = "video/x-m4v";
722         } else if (returnFileName.equals("mng")) {
723             contentType = "video/x-mng";
724         } else if (returnFileName.equals("asx") || returnFileName.equals("asf")) {
725             contentType = "video/x-ms-asf";
726         } else if (returnFileName.equals("wmv")) {
727             contentType = "video/x-ms-wmv";
728         } else if (returnFileName.equals("avi")) {
729             contentType = "video/x-msvideo";
730         }
731         return contentType;
732     }
733     
734     /**
735      * 向浏览器发送文件下载,支持断点续传
736      * @param file 要下载的文件
737      * @param request 请求对象
738      * @param response 响应对象
739      * @return 返回错误信息,无错误信息返回null
740      */
741     public static String downFile(File file, HttpServletRequest request, HttpServletResponse response){
742          return downFile(file, request, response, null);
743     }
744     
745     /**
746      * 向浏览器发送文件下载,支持断点续传
747      * @param file 要下载的文件
748      * @param request 请求对象
749      * @param response 响应对象
750      * @param fileName 指定下载的文件名
751      * @return 返回错误信息,无错误信息返回null
752      */
753     public static String downFile(File file, HttpServletRequest request, HttpServletResponse response, String fileName){
754         String error  = null;
755         if (file != null && file.exists()) {
756             if (file.isFile()) {
757                 if (file.length() <= 0) {
758                     error = "该文件是一个空文件。";
759                 }
760                 if (!file.canRead()) {
761                     error = "该文件没有读取权限。";
762                 }
763             } else {
764                 error = "该文件是一个文件夹。";
765             }
766         } else {
767             error = "文件已丢失或不存在!";
768         }
769         if (error != null){
770             logger.debug("---------------" + file + " " + error);
771             return error;
772         }
773 
774         long fileLength = file.length(); // 记录文件大小
775         long pastLength = 0;     // 记录已下载文件大小
776         int rangeSwitch = 0;     // 0:从头开始的全文下载;1:从某字节开始的下载(bytes=27000-);2:从某字节开始到某字节结束的下载(bytes=27000-39000)
777         long toLength = 0;         // 记录客户端需要下载的字节段的最后一个字节偏移量(比如bytes=27000-39000,则这个值是为39000)
778         long contentLength = 0; // 客户端请求的字节总量
779         String rangeBytes = ""; // 记录客户端传来的形如“bytes=27000-”或者“bytes=27000-39000”的内容
780         RandomAccessFile raf = null; // 负责读取数据
781         OutputStream os = null;     // 写出数据
782         OutputStream out = null;     // 缓冲
783         byte b[] = new byte[1024];     // 暂存容器
784 
785         if (request.getHeader("Range") != null) { // 客户端请求的下载的文件块的开始字节
786             response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);
787             logger.debug("request.getHeader(\"Range\") = " + request.getHeader("Range"));
788             rangeBytes = request.getHeader("Range").replaceAll("bytes=", "");
789             if (rangeBytes.indexOf('-') == rangeBytes.length() - 1) {// bytes=969998336-
790                 rangeSwitch = 1;
791                 rangeBytes = rangeBytes.substring(0, rangeBytes.indexOf('-'));
792                 pastLength = Long.parseLong(rangeBytes.trim());
793                 contentLength = fileLength - pastLength; // 客户端请求的是 969998336  之后的字节
794             } else { // bytes=1275856879-1275877358
795                 rangeSwitch = 2;
796                 String temp0 = rangeBytes.substring(0, rangeBytes.indexOf('-'));
797                 String temp2 = rangeBytes.substring(rangeBytes.indexOf('-') + 1, rangeBytes.length());
798                 pastLength = Long.parseLong(temp0.trim()); // bytes=1275856879-1275877358,从第 1275856879 个字节开始下载
799                 toLength = Long.parseLong(temp2); // bytes=1275856879-1275877358,到第 1275877358 个字节结束
800                 contentLength = toLength - pastLength; // 客户端请求的是 1275856879-1275877358 之间的字节
801             }
802         } else { // 从开始进行下载
803             contentLength = fileLength; // 客户端要求全文下载
804         }
805 
806         // 如果设设置了Content-Length,则客户端会自动进行多线程下载。如果不希望支持多线程,则不要设置这个参数。 响应的格式是:
807         // Content-Length: [文件的总大小] - [客户端请求的下载的文件块的开始字节]
808         // ServletActionContext.getResponse().setHeader("Content- Length", new Long(file.length() - p).toString());
809         response.reset(); // 告诉客户端允许断点续传多线程连接下载,响应的格式是:Accept-Ranges: bytes
810         if (pastLength != 0) {
811             response.setHeader("Accept-Ranges", "bytes");// 如果是第一次下,还没有断点续传,状态是默认的 200,无需显式设置;响应的格式是:HTTP/1.1 200 OK
812             // 不是从最开始下载, 响应的格式是: Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小]
813             logger.debug("---------------不是从开始进行下载!服务器即将开始断点续传...");
814             switch (rangeSwitch) {
815                 case 1: { // 针对 bytes=27000- 的请求
816                     String contentRange = new StringBuffer("bytes ").append(new Long(pastLength).toString()).append("-")
817                             .append(new Long(fileLength - 1).toString()).append("/").append(new Long(fileLength).toString()).toString();
818                     response.setHeader("Content-Range", contentRange);
819                     break;
820                 }
821                 case 2: { // 针对 bytes=27000-39000 的请求
822                     String contentRange = rangeBytes + "/" + new Long(fileLength).toString();
823                     response.setHeader("Content-Range", contentRange);
824                     break;
825                 }
826                 default: {
827                     break;
828                 }
829             }
830         } else {
831             // 是从开始下载
832             logger.debug("---------------是从开始进行下载!");
833         }
834 
835         try {
836             /*response.addHeader("Content-Disposition", "attachment; filename=\"" +
837                     Encodes.urlEncode(StringUtils.isBlank(fileName) ? file.getName() : fileName) + "\"");
838             response.setContentType(getContentType(file.getName())); // set the MIME type.*/
839             String agent = (String)request.getHeader("USER-AGENT");
840             if(agent != null && agent.toLowerCase().indexOf("firefox") > 0){
841                 //response.addHeader("Content-Disposition", "attachment; filename=\"" + new String(Base64.encodeBase64(fileName.getBytes("UTF-8")),"iso-8859-1")+ "\"");
842                 //response.setCharacterEncoding("utf-8");
843                 //response.addHeader("Content-Disposition", "attachment; filename=\"" + new String(fileName.getBytes("gb2312"),"ISO-8859-1")+ "\"");
844                 //String enableFileName = "=?UTF-8?B?\"" + (new String(Base64.encodeBase64(fileName.getBytes("UTF-8")),"UTF-8")) + "\"?=";
845                 String enableFileName = "\"" + new String(fileName.getBytes("UTF-8"),"iso-8859-1") + "\"";
846                 response.setHeader("Content-Disposition", "attachment; filename=" + enableFileName);
847             }else{
848                 response.addHeader("Content-Disposition", "attachment; filename=\"" +
849                         java.net.URLEncoder.encode(StringUtils.isBlank(fileName) ? file.getName() : fileName,"UTF-8") + "\"");
850             }
851             response.setContentType(getContentType(file.getName())); // set the MIME type.
852             response.addHeader("Content-Length", String.valueOf(contentLength));
853             os = response.getOutputStream();
854             out = new BufferedOutputStream(os);
855             raf = new RandomAccessFile(file, "r");
856             try {
857                 switch (rangeSwitch) {
858                     case 0: { // 普通下载,或者从头开始的下载 同1
859                     }
860                     case 1: { // 针对 bytes=27000- 的请求
861                         raf.seek(pastLength); // 形如 bytes=969998336- 的客户端请求,跳过 969998336 个字节
862                         int n = 0;
863                         while ((n = raf.read(b, 0, 1024)) != -1) {
864                             out.write(b, 0, n);
865                         }
866                         break;
867                     }
868                     case 2: { // 针对 bytes=27000-39000 的请求
869                         raf.seek(pastLength); // 形如 bytes=1275856879-1275877358 的客户端请求,找到第 1275856879 个字节
870                         int n = 0;
871                         long readLength = 0; // 记录已读字节数
872                         while (readLength <= contentLength - 1024) {// 大部分字节在这里读取
873                             n = raf.read(b, 0, 1024);
874                             readLength += 1024;
875                             out.write(b, 0, n);
876                         }
877                         if (readLength <= contentLength) { // 余下的不足 1024 个字节在这里读取
878                             n = raf.read(b, 0, (int) (contentLength - readLength));
879                             out.write(b, 0, n);
880                         }
881                         break;
882                     }
883                     default: {
884                         break;
885                     }
886                 }
887                 out.flush();
888                 logger.debug("---------------下载完成!");
889             } catch (IOException ie) {
890                 /**
891                  * 在写数据的时候, 对于 ClientAbortException 之类的异常,
892                  * 是因为客户端取消了下载,而服务器端继续向浏览器写入数据时, 抛出这个异常,这个是正常的。
893                  * 尤其是对于迅雷这种吸血的客户端软件, 明明已经有一个线程在读取 bytes=1275856879-1275877358,
894                  * 如果短时间内没有读取完毕,迅雷会再启第二个、第三个。。。线程来读取相同的字节段, 直到有一个线程读取完毕,迅雷会 KILL
895                  * 掉其他正在下载同一字节段的线程, 强行中止字节读出,造成服务器抛 ClientAbortException。
896                  * 所以,我们忽略这种异常
897                  */
898                 logger.debug("提醒:向客户端传输时出现IO异常,但此异常是允许的,有可能客户端取消了下载,导致此异常,不用关心!");
899             }
900         } catch (Exception e) {
901             logger.error(e.getMessage(), e);
902         } finally {
903             if (out != null) {
904                 try {
905                     out.close();
906                 } catch (IOException e) {
907                     logger.error(e.getMessage(), e);
908                 }
909             }
910             if (raf != null) {
911                 try {
912                     raf.close();
913                 } catch (IOException e) {
914                     logger.error(e.getMessage(), e);
915                 }
916             }
917         }
918         return null;
919     }
920 
921     /**
922      * 修正路径,将 \\ 或 / 等替换为 File.separator
923      * @param path 待修正的路径
924      * @return 修正后的路径
925      */
926     public static String path(String path){
927         String p = StringUtils.replace(path, "\\", "/");
928         p = StringUtils.join(StringUtils.split(p, "/"), "/");
929         if (!StringUtils.startsWithAny(p, "/") && StringUtils.startsWithAny(path, "\\", "/")){
930             p += "/";
931         }
932         if (!StringUtils.endsWithAny(p, "/") && StringUtils.endsWithAny(path, "\\", "/")){
933             p = p + "/";
934         }
935         if (path != null && path.startsWith("/")){
936             p = "/" + p; // linux下路径
937         }
938         return p;
939     }
940     
941     /**
942      * 获目录下的文件列表
943      * @param dir 搜索目录
944      * @param searchDirs 是否是搜索目录
945      * @return 文件列表
946      */
947     public static List<String> findChildrenList(File dir, boolean searchDirs) {
948         List<String> files = Lists.newArrayList();
949         for (String subFiles : dir.list()) {
950             File file = new File(dir + "/" + subFiles);
951             if (((searchDirs) && (file.isDirectory())) || ((!searchDirs) && (!file.isDirectory()))) {
952                 files.add(file.getName());
953             }
954         }
955         return files;
956     }
957 
958     /**
959      * 获取文件扩展名(返回小写)
960      * @param fileName 文件名
961      * @return 例如:test.jpg  返回:  jpg
962      */
963     public static String getFileExtension(String fileName) {
964         if ((fileName == null) || (fileName.lastIndexOf(".") == -1) || (fileName.lastIndexOf(".") == fileName.length() - 1)) {
965             return null;
966         }
967         return StringUtils.lowerCase(fileName.substring(fileName.lastIndexOf(".") + 1));
968     }
969 
970     /**
971      * 获取文件名,不包含扩展名
972      * @param fileName 文件名
973      * @return 例如:d:\files\test.jpg  返回:d:\files\test
974      */
975     public static String getFileNameWithoutExtension(String fileName) {
976         if ((fileName == null) || (fileName.lastIndexOf(".") == -1)) {
977             return null;
978         }
979         return fileName.substring(0, fileName.lastIndexOf("."));
980     }
981 }

 

 大家用到那个可以去试一试   真的很好用啦

 有不对的地方还请大家 相互交流一下啦

 

posted @ 2018-06-12 15:03  胖头陀春天  阅读(330)  评论(0编辑  收藏  举报