package cn.com.ctop.shiwan.modules;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @ClassName ZipUtil
 * @Author ZHAOXA
 * @date 2020-10-23 10:05
 */
@Slf4j
public class FileUtil {

    /**
     * 转MultipartFile格式文件
     *
     * @param
     * @return org.springframework.web.multipart.MultipartFile
     * @throws
     * @author ZHAOXA
     */
    public static MultipartFile getMulFileByPath(String picPath) {
        FileItem fileItem = createFileItem(picPath);
        MultipartFile mfile = new CommonsMultipartFile(fileItem);
        return mfile;
    }

    private static FileItem createFileItem(String filePath) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        String textFieldName = "textField";
        int num = filePath.lastIndexOf("/");
        String fileName = filePath.substring(num);
        FileItem item = factory.createItem(textFieldName, "text/plain", true,
                fileName);
        File newfile = new File(filePath);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        try {
            FileInputStream fis = new FileInputStream(newfile);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192))
                    != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return item;
    }


    /**
     * 下载文件到本地
     *
     * @param locationPath 本地路径
     * @param fileUrl      文件下载路径
     * @param fileName     下载后的名称含后缀
     * @return java.lang.String
     * @throws
     * @author ZHAOXA
     */
    public static String writeFiles(String locationPath, String fileUrl, String fileName) {
        InputStream is = null;
        OutputStream os = null;
        Date date = new Date();
        String realPath = null;
        try {
            URL url = new URL(fileUrl);
            is = url.openStream();
            File file = new File(locationPath);
            if (!file.exists()) {
                boolean mkdirFlag = file.mkdirs();
                if (!mkdirFlag) {
                    log.error("[ ========== 下载，创建临时文件夹失败 ========== ]");
                    return null;
                }
            }
            realPath = locationPath.concat(fileName);
            os = new FileOutputStream(realPath);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = is.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
                os.flush();
            }

        } catch (Exception e) {
            log.error(" ========== 文件下载到本地异常：", e);
            return null;
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return realPath;
    }

    /**
     * 通过MultipartFile获取本地下载路径
     *
     * @param
     * @return java.lang.String
     * @throws
     * @author ZHAOXA
     */
    public static String approvalFile(MultipartFile filecontent, String path) {
        OutputStream os = null;
        InputStream inputStream = null;
        String fileName = filecontent.getOriginalFilename();
        try {
            inputStream = filecontent.getInputStream();
        } catch (IOException e) {
            log.error("获取文件流异常");
        }
        try {
            byte[] bs = new byte[1024];
            // 读取到的数据长度
            int len;
            // 输出的文件流保存到本地文件
            File tempFile = new File(path);
            if (!tempFile.exists()) {
                tempFile.mkdirs();
            }
            os = new FileOutputStream(tempFile.getPath() + "/" + File.separator + fileName);
            // 开始读取
            while ((len = inputStream.read(bs)) != -1) {
                os.write(bs, 0, len);
            }
        } catch (Exception e) {
            log.error("获取文件的本地路径失败", e);
        } finally {
            // 完毕，关闭所有链接
            try {
                os.close();
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return path + fileName;
    }


    /**
     * @param zipSavePath 压缩好的zip包存放路径
     * @param sourceFile  待压缩的文件（单个文件或者整个文件目录）
     * @return
     * @author
     */
    public static String zipCompress(String zipSavePath, File sourceFile) {
        try {
            //创建zip输出流
            ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipSavePath));
            File[] fileList = sourceFile.listFiles();
            //如果文件夹为空，则只需在目的地zip文件中写入一个目录进入点
            if (fileList.length != 0) {
                for (File file : fileList) {
                    compress(zos, file, file.getName());
                }
                zos.close();
            }
        } catch (Exception e) {
            log.error("压缩文件异常 : {}, zipSavePath={}, sourceFile={}", e, zipSavePath, sourceFile.getName());
        }
        return zipSavePath;
    }

    /**
     * 递归压缩文件
     *
     * @param
     * @return void
     * @throws
     * @author ZHAOXA
     */
    private static void compress(ZipOutputStream zos, File sourceFile, String fileName) throws Exception {
        if (sourceFile.isDirectory()) {
            //如果是文件夹，取出文件夹中的文件（或子文件夹）
            File[] fileList = sourceFile.listFiles();
            if (fileList.length == 0)//如果文件夹为空，则只需在目的地zip文件中写入一个目录进入点
            {
                zos.putNextEntry(new ZipEntry(fileName + "/"));
            } else//如果文件夹不为空，则递归调用compress，文件夹中的每一个文件（或文件夹）进行压缩
            {
                for (File file : fileList) {
                    compress(zos, file, fileName + "/" + file.getName());
                }
            }
        } else {
            if (!sourceFile.exists()) {
                zos.putNextEntry(new ZipEntry("/"));
                zos.closeEntry();
            } else {
                //单个文件，直接将其压缩到zip包中
                zos.putNextEntry(new ZipEntry(fileName));
                FileInputStream fis = new FileInputStream(sourceFile);
                byte[] buf = new byte[1024];
                int len;
                //将源文件写入到zip文件中
                while ((len = fis.read(buf)) != -1) {
                    zos.write(buf, 0, len);
                }
                zos.closeEntry();
                fis.close();
            }
        }
    }


}
