yanghb
2024-12-17 1287337fd0b0c156ec79712f9a600ebeffefe3a6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
package com.zzg.common.utils;
 
import com.zzg.common.utils.enums.FileHeadEnum;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;
 
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Base64;
import java.util.List;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
 
/**
 * Description: 文件处理工具类
 *
 * @author wangjiang
 * @date 2018/11/12
 */
public class FileUtil {
 
    private FileUtil() {
        throw new IllegalStateException("Utility class");
    }
 
    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(FileUtil.class);
 
    /**
     * 后缀名与文件名的分隔符
     */
    public static final String FILE_PUF = ".";
 
    public static final long KB = 1024L;
 
    /**
     * 文件大小单位转换
     *
     * @param size
     * @return
     */
    public static String getSize(long size) {
        if (size >= KB * KB * KB) {
            return size / KB * KB * KB + " GB";
        } else if (size >= KB * KB) {
            return size / KB * KB + " MB";
        } else if (size >= KB) {
            return size / KB + " KB";
        } else {
            return size + " B";
        }
    }
 
 
    /**
     * 将 MultipartFile 转换为 File
     *
     * @param multipartFile 要转换的 MultipartFile 对象
     * @return 转换后的 File 对象
     * @throws IOException 如果文件处理过程中出现错误
     */
    public static File convertToFile(MultipartFile multipartFile) throws IOException {
        // 创建临时文件
        File file = File.createTempFile("temp", multipartFile.getOriginalFilename());
 
        try (FileOutputStream fos = new FileOutputStream(file)) {
            // 将 MultipartFile 的内容写入到 File 中
            fos.write(multipartFile.getBytes());
        }
 
        // 返回 File 对象
        return file;
    }
 
    /**
     * 获取文件后缀名
     *
     * @param fileName
     * @return
     */
    public static String getSuffix(String fileName) {
        return fileName.substring(fileName.lastIndexOf(FILE_PUF) + 1);
    }
 
    /**
     * 去掉文件后缀名
     *
     * @param fileName
     * @return
     */
    public static String removeSuffix(String fileName) {
        return fileName.substring(0, fileName.lastIndexOf(FILE_PUF));
    }
 
    /**
     * 保存文件
     *
     * @param inputStream 输入流
     * @param pathName    要保存的文件名
     * @see #saveFile(InputStream, File)
     */
    public static void saveFile(InputStream inputStream, String pathName) {
        saveFile(inputStream, new File(pathName));
    }
 
    /**
     * 保存文件
     *
     * @param inputStream 输入流
     * @param file        要保存的文件
     */
    public static void saveFile(InputStream inputStream, File file) {
        try {
            FileUtils.copyInputStreamToFile(inputStream, file);
        } catch (IOException e) {
            log.error("保存文件失败", e);
            throw new RuntimeException("文件保存失败");
        }
    }
 
 
    /**
     * @param file     要输出的文件
     * @param fileName 下载时的文件名
     * @see #outFile(InputStream, String, String)
     */
    public static void outFile(File file, String fileName) {
        try (InputStream inputStream = FileUtils.openInputStream(file)) {
            outFile(inputStream, fileName, String.valueOf(file.length()));
        } catch (IOException e) {
            throw new RuntimeException("打开服务器文件失败" + e.getMessage(), e);
        }
    }
 
    /**
     * 实现文件下载
     *
     * @param input    输入流
     * @param fileName 文件名
     * @see #setOutFileHeader(HttpServletResponse, String, String)
     */
    public static void outFile(InputStream input, String fileName, String length) throws IOException {
        try {
            HttpServletResponse response = ContextUtil.getServletResponse();
            setOutFileHeader(response, fileName, length);
            OutputStream output = response.getOutputStream();
            IOUtils.copyLarge(input, output);
            output.close();
            input.close();
        } catch (IOException e) {
            throw new RuntimeException("文件输出失败", e);
        }
    }
 
    /**
     * 拷贝文件到指定目录
     *
     * @param fileNames
     * @param destDir
     * @throws IOException
     */
    public static void synFiles(List<String> fileNames, String destDir) throws IOException {
        List<File> files = fileNames.stream().map(File::new).collect(Collectors.toList());
        File destFile = new File(destDir);
        if (!destFile.exists()) {
            boolean bool = destFile.mkdirs();
            if (!destFile.isDirectory() || !bool) {
                throw new IllegalAccessError("目录:" + destDir + "创建失败");
            }
        }
        FileUtils.copyToDirectory(files, destFile);
    }
 
    /**
     * @param response 响应请求
     * @param fileName 下载的文件名字
     * @param length   下载文件的长度
     */
    public static void setOutFileHeader(HttpServletResponse response, String fileName, String length) {
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        try {
            String encode = URLEncoder.encode(fileName, "UTF-8");
            response.addHeader("Content-Disposition", "attachment; filename=\"" + encode + "\"");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("设置下载文件响应头失败!", e);
        }
        if (StringUtils.isNotBlank(length)) {
            response.addHeader("Content-Length", length);
        }
    }
 
    /**
     * @see #copyZipOut(ZipOutputStream, InputStream, ZipEntry)
     */
    public static void copyZipOut(ZipOutputStream outputStream, File... files) {
        for (File file : files) {
            try (InputStream inputStream = FileUtils.openInputStream(file)) {
                copyZipOut(outputStream, inputStream, new ZipEntry(file.getName()));
            } catch (IOException e) {
                throw new RuntimeException("打开服务器文件失败" + e.getMessage(), e);
            }
        }
    }
 
    /**
     * 将一个输入流数据 输出到压缩包里
     *
     * @param outputStream 输出流
     * @param inputStream  输入流
     * @param zipEntry     压缩对象
     */
    public static void copyZipOut(ZipOutputStream outputStream, InputStream inputStream, ZipEntry zipEntry) {
        try {
            outputStream.putNextEntry(zipEntry);
            IOUtils.copyLarge(inputStream, outputStream);
            outputStream.closeEntry();
        } catch (IOException e) {
            throw new RuntimeException("zip压缩输出文件:" + zipEntry.getName() + "时失败", e);
        }
    }
 
    /**
     * @param folder   文件夹
     * @param response
     */
    public static void copyZipOut(String folder, HttpServletResponse response) {
        ZipOutputStream out = null;
        BufferedOutputStream bos = null;
        try {
            File sourceFile = new File(folder);
            //将zip以流的形式输出到前台
            response.setHeader("content-type", "application/octet-stream");
//            long size = FileUtils.sizeOf(sourceFile);
//            response.setHeader("Content-Length", String.valueOf(size));
            // 设置浏览器响应头对应的Content-disposition
            response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("档案管理.zip", "UTF-8"));
            response.setCharacterEncoding("utf-8");
            //创建zip输出流
            out = new ZipOutputStream(response.getOutputStream());
            //创建缓冲输出流
            bos = new BufferedOutputStream(out);
            //调用压缩函数
            compress(out, bos, sourceFile, sourceFile.getName());
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOCloseUtil.close(bos, out);
        }
    }
 
    /**
     * 文件压缩
     *
     * @param out
     * @param bos
     * @param sourceFile
     * @param base
     */
    public static void compress(ZipOutputStream out, BufferedOutputStream bos, File sourceFile, String base) {
        FileInputStream fos = null;
        BufferedInputStream bis = null;
        try {
            //如果路径为目录(文件夹)
            if (sourceFile.isDirectory()) {
                //取出文件夹中的文件(或子文件夹)
                File[] flist = sourceFile.listFiles();
                if (flist.length == 0) {//如果文件夹为空,则只需在目的地zip文件中写入一个目录进入点
                    out.putNextEntry(new ZipEntry(base + "/"));
                } else {//如果文件夹不为空,则递归调用compress,文件夹中的每一个文件(或文件夹)进行压缩
                    for (int i = 0; i < flist.length; i++) {
                        compress(out, bos, flist[i], base + "/" + flist[i].getName());
                    }
                }
            } else {//如果不是目录(文件夹),即为文件,则先写入目录进入点,之后将文件写入zip文件中
                out.putNextEntry(new ZipEntry(base));
                fos = new FileInputStream(sourceFile);
                bis = new BufferedInputStream(fos);
                int tag;
                //将源文件写入到zip文件中
                while ((tag = bis.read()) != -1) {
                    out.write(tag);
                }
                bis.close();
                fos.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOCloseUtil.close(bis, fos);
        }
    }
 
 
    /**
     * @param file     要输出的文件
     * @param fileName 下载时的文件名
     * @param token    要传输的token
     * @see #outFileAndToken(InputStream, String, String, String)
     */
    public static void outFileAndToken(File file, String fileName, String token) {
        try (InputStream inputStream = FileUtils.openInputStream(file)) {
            outFileAndToken(inputStream, fileName, String.valueOf(file.length()), token);
        } catch (IOException e) {
            throw new RuntimeException("打开服务器文件失败" + e.getMessage(), e);
        }
    }
 
    /**
     * 实现文件下载
     *
     * @param input    输入流
     * @param fileName 文件名
     * @param token    要传输的token
     * @see #setOutFileHeader(HttpServletResponse, String, String)
     */
    public static void outFileAndToken(InputStream input, String fileName, String length, String token) {
        try {
            HttpServletResponse response = ContextUtil.getServletResponse();
            response.addHeader("token", token);
            setOutFileHeader(response, fileName, length);
            OutputStream output = response.getOutputStream();
            IOUtils.copyLarge(input, output);
        } catch (IOException e) {
            throw new RuntimeException("文件输出失败", e);
        }
    }
 
    /**
     * 输出图片
     */
    public static void outImg(HttpServletResponse response, String path) {
        FileInputStream fis = null;
        response.setContentType("image/gif");
        try {
            OutputStream out = response.getOutputStream();
            File file = new File(path);
            fis = new FileInputStream(file);
            byte[] b = new byte[fis.available()];
            fis.read(b);
            out.write(b);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
 
    /**
     * 输出图片
     */
    public static void outArcgisNode(HttpServletResponse response, String path) {
        FileInputStream fis = null;
        try {
            OutputStream out = response.getOutputStream();
            File file = new File(path);
            fis = new FileInputStream(file);
            byte[] b = new byte[fis.available()];
            fis.read(b);
            out.write(b);
            out.flush();
        } catch (Exception e) {
            log.error("outArcgisNode error: {}", e.getMessage());
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
 
    /**
     * 图片转base64
     */
    public static String transformPictureToBase64Data(String LoadPath, String DataName, String fileType) {
        Base64.Encoder encoder = Base64.getEncoder();  //获取Base64编码器
        byte[] ImgContainer;    //数据集缓存器
        FileInputStream fileInputStream = null; //文件输入流
        try {
            fileInputStream = new FileInputStream(LoadPath + DataName);    //到指定路径寻找文件
            ImgContainer = new byte[fileInputStream.available()];          //设置图片字节数据缓冲区大小
            fileInputStream.read(ImgContainer);           //将数据流中的图片数据读进缓冲区
            String Base64ImgData = String.format("data:image/%s;base64,%s", fileType, encoder.encodeToString(ImgContainer));  //将图片编码转换成Base64格式的数据集
            fileInputStream.close();      //关闭数据流
            return Base64ImgData;  //将缓冲区数据转换成字符数据返回
        } catch (FileNotFoundException e) {
            return "找不到指定文件!";
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "null";
    }
 
 
    /**
     * 获取文件的原始头信息
     * 判断文件后缀
     *
     * @param fis
     * @return true:格式无异常 false:格式异常
     */
    public static boolean CheckFileHead(FileInputStream fis) {
        StringBuilder stringBuilder = new StringBuilder();
        try {
            //大小不同,获取的文件头长度也不一样
            byte[] b = new byte[4];
            fis.read(b, 0, b.length);
            if (b == null || b.length <= 0) {
                return false;
            }
            for (int i = 0; i < b.length; i++) {
                // 以十六进制(基数 16)无符号整数形式返回一个整数参数的字符串表示形式
                int v = b[i] & 0xFF;
                String hv = Integer.toHexString(v);
                if (hv.length() < 2) {
                    stringBuilder.append(0);
                }
                stringBuilder.append(hv);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        String head = stringBuilder.toString();
        String code = FileHeadEnum.getSuffixByCode(head);
 
        return org.apache.commons.lang3.StringUtils.isNotEmpty(code);
    }
 
    /**
     * 获取下载路径
     *
     * @param uploadDir 文件夹
     * @param fileName  文件名称
     */
    public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException {
        File desc = new File(uploadDir + File.separator + fileName);
 
        if (!desc.getParentFile().exists()) {
            desc.getParentFile().mkdirs();
        }
        if (!desc.exists()) {
            desc.createNewFile();
        }
        return desc;
    }
 
 
    /**
     * 复制文件
     *
     * @param sourcePath 源文件绝对路径
     * @param targetPath 目标文件绝对路径
     * @throws Exception 异常
     */
    public static void copy(String sourcePath, String targetPath) throws Exception {
        //字节输入流,用来读取文件
        FileInputStream in = new FileInputStream(new File(sourcePath));
        //字节输出流,用来写文件
        FileOutputStream out = new FileOutputStream(new File(targetPath));
        byte[] buff = new byte[512];
        int n = 0;
        while ((n = in.read(buff)) != -1) {
            out.write(buff, 0, n);
        }
        out.flush();
        in.close();
        out.close();
        System.out.println("复制完成");
    }
 
    /**
     * 根据路径删除指定的目录或文件,无论存在与否
     *
     * @param sPath 要删除的目录或文件
     * @return 删除成功返回 true,否则返回 false。
     */
    public static boolean deleteFolder(String sPath) {
        boolean flag = false;
        File file = new File(sPath);
        // 判断目录或文件是否存在
        if (!file.exists()) {  // 不存在返回 false
            return flag;
        } else {
            // 判断是否为文件
            if (file.isFile()) {  // 为文件时调用删除文件方法
                return deleteFile(sPath);
            } else {  // 为目录时调用删除目录方法
                return deleteDirectory(sPath);
            }
        }
    }
 
    /**
     * 删除单个文件
     *
     * @param sPath 被删除文件的文件名
     * @return 单个文件删除成功返回true,否则返回false
     */
    public static boolean deleteFile(String sPath) {
        boolean flag = false;
        File file = new File(sPath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists()) {
            file.delete();
            flag = true;
        }
        return flag;
    }
 
    /**
     * 删除目录(文件夹)以及目录下的文件
     *
     * @param sPath 被删除目录的文件路径
     * @return 目录删除成功返回true,否则返回false
     */
    public static boolean deleteDirectory(String sPath) {
        //如果sPath不以文件分隔符结尾,自动添加文件分隔符
        if (!sPath.endsWith(File.separator)) {
            sPath = sPath + File.separator;
        }
        File dirFile = new File(sPath);
        //如果dir对应的文件不存在,或者不是一个目录,则退出
        if (!dirFile.exists() || !dirFile.isDirectory()) {
            return false;
        }
        boolean flag = true;
        //删除文件夹下的所有文件(包括子目录)
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            //删除子文件
            if (files[i].isFile()) {
                flag = deleteFile(files[i].getAbsolutePath());
                if (!flag) break;
            } //删除子目录
            else {
                flag = deleteDirectory(files[i].getAbsolutePath());
                if (!flag) break;
            }
        }
        if (!flag) return false;
        //删除当前目录
        if (dirFile.delete()) {
            return true;
        } else {
            return false;
        }
    }
}