文件转pdf

news2024/9/19 22:59:50

背景

项目中很多预览工具,文件转pdf预览,采用libreoffice6.1插件实现

环境说明

系统CentOS:CentOS7  

libreoffice:6.1

下载

中文官网 https://zh-cn.libreoffice.org/download/libreoffice/

 下载其他老版本

Index of /libreoffice/old

 

某云盘

安装

1.上传到/opt 目录

2.解压

tar -zxvf  LibreOffice_6.1.6_Linux_x86-64_rpm.tar.gz

3.安装

cd LibreOffice_6.1.6.3_Linux_x86-64_rpm/RPMS

yum localinstall *.rpm

4.查看安装目录

which libreoffice6.1

转化测试

在/opt 目录上传测试文件

执行

/usr/bin/libreoffice6.1 --headless --invisible --convert-to pdf  ./需求梳理.docx   --outdir    ./

生成需求梳理.pdf 并下载到本地

 

打开中文乱码

解决中文乱码

看原有字体

cd /usr/share/fonts/

安装字体

 yum groupinstall "fonts"

 查看 /usr/share/fonts/目录下出现很多字体

重新生成pdf测试

 下载 打开后不乱码 这是我打马赛克

 

安装出现的问题

转化是出现 错误
/opt/libreoffice6.1/program/soffice.bin: error while loading shared libraries: libcairo.so.2: cannot open shared object file: No such file or directory

到/opt/libreoffice6.1/program/  目录下执行

soffice -help

报错

/opt/libreoffice6.1/program/soffice.bin: error while loading shared libraries: libcairo.so.2: cannot open shared object file: No such file or directory

执行命令:
yum install cairo
后再次执行命令:/opt/libreoffice6.1/program/soffice -help

报错

/opt/libreoffice6.1/program/soffice.bin: error while loading shared libraries: libcairo.so.2: cannot open shared object file: No such file or directory

yum install cups-libs
后,再次执行命令:/opt/libreoffice6.1/program/soffice -help

报错

/opt/libreoffice6.1/program/soffice.bin: error while loading shared libraries: libcairo.so.2: cannot open shared object file: No such file or directory

yum install libSM

后,再次执行:/opt/libreoffice6.1/program/soffice -help

 libreoffice的相关命令出来了,libreoffice安装成功

通过java结合libreoffice 转pdf

实现文件预览

代码

package com.cloud.user.controller;

import com.cloud.user.bean.po.CloudFile;
import com.cloud.user.service.UploaderService;
import com.cloud.user.util.FileUploadUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.List;

@RestController
@RequestMapping("uploader")
public class TestUploader {



   //-----------------------普通上传----------------非分片

    /**
     *普通上传  和 上传时并生成pdf文件 用于预览  也可抽出来单独 调用请求预览 此处生成预览前置 避免每次预览时生成
     * @param file
     * @return
     */
    @PostMapping("/uploadFiles")
    public String uploadFiles(@RequestParam("file") MultipartFile[] file) {
         List<CloudFile > list= uploaderService.uploadFiles(file);
        return "SUCCESS";
    }




}
package com.cloud.user.service;

import com.cloud.user.bean.po.CloudFile;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

public interface UploaderService {


    /**
     *  检查分片是否存在
     * @param md5Value
     * @param chunk
     * @param moduleName
     * @param fileTypeKey
     * @return
     */
    Boolean checkChunk(String md5Value, Integer chunk, String moduleName, String fileTypeKey);

    /**
     *  上传分片
     * @param file
     * @param md5Value
     * @param chunk
     * @param moduleName
     * @param fileTypeKey
     * @return
     */
    Boolean uploadChunk(MultipartFile file, String md5Value, Integer chunk, String moduleName, String fileTypeKey);

    /**
     * 合并分片
     * @param chunkCount
     * @param md5Value
     * @param fileName
     * @param moduleName
     * @param fileTypeKey
     * @return
     */
    String merge(Integer chunkCount, String md5Value, String fileName, String moduleName, String fileTypeKey);

    /**
     * 获取上传目录
     * @param fileTypeKey
     * @return
     */
    String specifiedDirectory(String moduleName,String fileTypeKey);

    /**
     * 根据文件id 获取文件全路径
     * @param fileId
     * @return
     */
    String getFilePathByFileId(String fileId);

    /**
     * 获取根路径
     * @return
     */
    String rootPath();

    /**
     * 普通上传  和 上传时并生成pdf文件 用于预览  也可抽出来单独 调用请求预览 此处生成预览前置 避免每次预览时生成
     * @param file
     * @return
     */
    List<CloudFile> uploadFiles(MultipartFile[] file);
}

package com.cloud.user.service.impl;

import com.cloud.framework.file.ResumeUploader;
import com.cloud.framework.util.ConstantUtils;
import com.cloud.framework.util.UUIDGenerator;
import com.cloud.user.bean.po.CloudFile;
import com.cloud.user.entity.db1.PanFile;
import com.cloud.user.properties.FileProperties;
import com.cloud.user.service.UploaderService;
import com.cloud.user.util.ConvertToPdfRunable;
import com.cloud.user.util.FileUploadUtils;
import com.cloud.user.util.Md5Util;
import com.cloud.user.util.ThreadPoolUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class UploaderServiceImpl implements UploaderService {


    private final ResumeUploader fileOperation;
    private final FileProperties fileProperties;

    public UploaderServiceImpl(Map<String, ResumeUploader> resumeUploader, FileProperties fileProperties) {
        this.fileOperation = resumeUploader.get(ConstantUtils.fs.UNC.name());
        this.fileProperties = fileProperties;
    }

    @Override
    public Boolean checkChunk(String md5Value, Integer chunk, String moduleName, String fileTypeKey) {
        String path = specifiedDirectory(moduleName, fileTypeKey);
        System.out.println("路径" + path);
        return fileOperation.checkChunk(path, md5Value, chunk);
    }

    @Override
    public Boolean uploadChunk(MultipartFile file, String md5Value, Integer chunk, String moduleName, String fileTypeKey) {
        String path = specifiedDirectory(moduleName, fileTypeKey);
        System.out.println("路径" + path);
        return fileOperation.upload(file, path, md5Value, chunk);
    }

    @Override

    public String merge(Integer chunkCount, String md5Value, String fileName, String moduleName, String fileTypeKey) {
        String path = specifiedDirectory(moduleName, fileTypeKey);
        System.out.println("路径" + path);
        // 目录下如果存在相同名称的文件,对文件名称做修改   xxx(1).txt  xxx(2).txt
        fileName = this.verifyRepeatFile(path, fileName, 0);
        Boolean merge = fileOperation.merge(path, path, md5Value, chunkCount, fileName);
        if (merge) {
            String filePath = path + fileName;
            CloudFile cloudFile = new CloudFile();
            cloudFile.setId(UUIDGenerator.getUUID());
            cloudFile.setMd5(Md5Util.fastMD5(new File(filePath)));
            cloudFile.setName(fileName.substring(0, fileName.lastIndexOf(".")));
            cloudFile.setType(fileName.substring(fileName.lastIndexOf(".")));
            cloudFile.setPath(filePath);
            cloudFile.setFileSize(new File(filePath).length());
            cloudFile.setGmtCreate(new Date());
            //存数据库
            // int save = cloudFileMapper.save(cloudFile);
            int save = 1;
            if (save > 0) {
                return cloudFile.getId();
            }
        }
        return null;
    }

    /**
     *
     * @param fileTypeKey 文件类型
     */
    /**
     * 根据模块名称 文件类型 获取指定文件目录  /根目录/模块名/类型名 存储目录
     *
     * @param moduleName  模块名称
     * @param fileTypeKey 文件类型
     * @return
     */
    @Override
    public String specifiedDirectory(String moduleName, String fileTypeKey) {
        // 文件根路径
        String rootPath = fileProperties.getBasePath();
        //软件
        if (moduleName.equals("app")) {
            rootPath = rootPath.endsWith(File.separator) ? rootPath : rootPath + File.separator;
            rootPath = rootPath + "app";
        }
        //项目
        if (moduleName.equals("project")) {
            rootPath = rootPath.endsWith(File.separator) ? rootPath : rootPath + File.separator;
            rootPath = rootPath + "project";
        }
        // 合并拼接路径
        rootPath = rootPath.endsWith(File.separator) ? rootPath : rootPath + File.separator;
        if (StringUtils.isNotBlank(fileTypeKey)) {
            rootPath = rootPath + fileTypeKey + File.separator;
        }
        return rootPath;
    }



    @Override
    public String getFilePathByFileId(String id) {
        return getFileFullPath(id);
    }

    @Override
    public String rootPath() {
        // 文件根路径
        String rootPath = fileProperties.getBasePath();
        rootPath = rootPath.endsWith(File.separator) ? rootPath : rootPath + File.separator;
        return rootPath;
    }


    private String getFileFullPath(String id) {
        //从db查  写死模拟
        //PanFile panFile = panFileManageMapper.getPanFile(id);
        PanFile panFile =new PanFile();
        panFile.setId(id);
        panFile.setParentId("0");
        panFile.setFileName("sc");
        String parentId = panFile.getParentId();
        if (!"0".equals(parentId)) {
            return getFileFullPath(parentId) + File.separator + panFile.getFileName();
        }
        return File.separator + panFile.getFileName();
    }


    /**
     * 目录下如果存在相同名称的文件,对文件名称做修改   xxx(1).txt  xxx(2).txt
     *
     * @param path
     * @param fileName
     * @param i
     * @return
     */
    private String verifyRepeatFile(String path, String fileName, int i) {
        String name = fileName.substring(0, fileName.lastIndexOf("."));
        String suffix = fileName.substring(fileName.lastIndexOf("."));

        String tempFileName;
        if (i != 0) {
            tempFileName = String.format("%s%s%d%s", name, "(", i, ")");
        } else {
            tempFileName = name;
        }
        File file = new File(path + tempFileName + suffix);
        if (file.exists()) {
            return verifyRepeatFile(path, name + suffix, ++i);
        }
        return tempFileName + suffix;
    }




    @Override
    public  List<CloudFile> uploadFiles(MultipartFile[] files) {
        String targetDirectoryPath = fileProperties.getProjectPath();
        File directoryFile = new File(targetDirectoryPath);
        if (!directoryFile.exists()) {
            directoryFile.mkdirs();
        }
        List<CloudFile> uploadFileList = new ArrayList<CloudFile>();
        for (int i = 0; files.length > i; i++) {
            long size;
            MultipartFile file = files[i];
            size = file.getSize();
            String sizeString = FileUploadUtils.readableFileSize(size);
            //上传
            String path = FileUploadUtils.upload(file, targetDirectoryPath);
            String prefix = FileUploadUtils.getPrefix(path);
            String suffix = FileUploadUtils.getSuffix(path);
            String suffixLowerCase = StringUtils.lowerCase(suffix);
            CloudFile cloudFile = new CloudFile();
            cloudFile.setId(UUIDGenerator.getUUID());
            cloudFile.setMd5(Md5Util.fastMD5(new File(path)));
            cloudFile.setName(file.getOriginalFilename());
            cloudFile.setType(suffix);
            cloudFile.setPath(path);
            cloudFile.setFileSize(new File(path).length());
            cloudFile.setGmtCreate(new Date());
            uploadFileList.add(cloudFile);
            //转pdf
            if (!FileUploadUtils.isType(file.getName(), FileUploadUtils.PDF)) {
                ConvertToPdfRunable convertToPdfRunable = new ConvertToPdfRunable(cloudFile.getId(), fileProperties.getPdfPath(), cloudFile.getPath());
                ThreadPoolUtil.PDF_SINGEL_STHREAD_POOL.execute(convertToPdfRunable);
            }
        }

        //存数据库
        // int save = cloudFileMapper.saves(uploadFileList);


        return uploadFileList;
    }

}

配置类

 

package com.cloud.user.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "file.uploader")
public class FileProperties {

    private String basePath;
    private String projectPath;
    private String pdfPath;


}
#type文件上传类型 account连接地址 pwd:密码 temp分片临时目录 isDelTempFile临时目录是否删除
   uploader:
      type: unc
      account:
      pwd:
      tempdir: temp
      isDelTempFile: true



# 文件上传路径 linux  basePath:/opt/dcp/   projectPath:${file.upload.basePath}project/  wind: basePath: D:\upload\ projectPath: ${file.upload.basePath}project\
file:
   uploader:
      basePath: /opt/dcp/
      projectPath: ${file.uploader.basePath}project/
      pdfPath: ${file.uploader.basePath}pdfTemp/

工具类

package com.cloud.user.util;

import cn.hutool.core.io.FileUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.File;

/**
 * 文件转pdf  采用libreoffice 插件
 */
@Slf4j
public class ConvertToPdfRunable implements Runnable {
    /**
     * 生成pdf文件地址
     */
   private String pdfPath;
    /**
     * 文件id
     */
    private String id;
    /**
     * 文件真实路径
     */
    private String filePath;

    public ConvertToPdfRunable(String id, String pdfPath, String filePath){
        this.pdfPath = pdfPath;
        this.id = id;
        this.filePath=filePath;
    }

    @Override
    public void run() {
        log.info("转pdf文档");
        boolean flag = false;
        String fileName = FileUploadUtils.getName(filePath);
        String suffix = FileUploadUtils.getSuffix(filePath);
        if (!CommonConstantUtils.FILE_TYPE_FILTER.contains(suffix)){
            log.info("{}类型不可转pdf格式",suffix);
            return;
        }
        log.info("文件名:{}",fileName);
        //处理文件名特殊字符 否则会 转pdf 失败
        for (char c : CommonConstantUtils.PDF_FILTER) {
            if (fileName.contains(String.valueOf(c))) {
                flag = true;
                break;
            }
        }
        if (flag){
            for (char c : CommonConstantUtils.PDF_FILTER) {
                fileName =fileName.replace(String.valueOf(c), "");
            }
            String sourcePath = filePath;
            filePath = pdfPath + fileName;
            FileUploadUtils.copy(sourcePath, filePath);
        }
        String s = FileUploadUtils.convertToPDF(filePath,pdfPath);
        log.info("生成预览地址:{}",s);
        String rename = FileUploadUtils.changeSuffix(id, FileUploadUtils.PDF);
        log.info("根据id生成预览文件名:{}",rename);
        File file = new File(s);
        log.info("预览文件:{}",file);
        File ff = FileUtil.rename(file, rename, true);
        log.info("预览文件改名后:{}",ff);
        log.info("生成的pdf文件路径:{},修改后路径:{}",s,ff.getPath());

    }
}
package com.cloud.user.util;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.RuntimeUtil;
import cn.hutool.system.OsInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.DecimalFormat;


@Slf4j
public class FileUploadUtils {

    /**
     * 点
     */
    public static final String DOT = ".";

    /**
     * 直接预览的文件类型(不通过LibreOffice转换)
     */
    public static final String PDF = "pdf";

    private static String transfer(MultipartFile file, File targetFile) {
        try {
            file.transferTo(targetFile);
        } catch (IllegalStateException | IOException e) {
            e.printStackTrace();
        }
        return targetFile.getPath();
    }

    private static void mkParentFile(File targetFile) {
        if (!targetFile.getParentFile().exists()) {
            targetFile.getParentFile().mkdirs();
        }
    }

    public static String readableFileSize(long size) {
        if (size <= 0) {
            return "0";
        }
        final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
        return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
    }


    /**
     * 文件上传
     *
     * @param file     文件
     * @param filePath 文件路径
     * @return 文件路径
     */
    public static String upload(MultipartFile file, String filePath) {
        File targetFile = new File(filePath, file.getOriginalFilename().replaceAll(" ", ""));
        mkParentFile(targetFile);
        return transfer(file, targetFile);
    }

    /**
     * 处理文件上传
     *
     * @param file       上传的文件
     * @param targetFile 目标文件
     * @return 上传文件目录
     */
    public static String upload(MultipartFile file, File targetFile) {
        mkParentFile(targetFile);
        return transfer(file, targetFile);
    }

    /**
     * 批量删除文件或文件夹
     *
     * @param filePaths 文件路径
     */
    public static void deletes(String[] filePaths) {
        for (String path : filePaths) {
            delete(path);
        }
    }

    /**
     * 删除文件或文件夹
     *
     * @param filePath 文件路径
     * @return 成功与否
     */
    public static boolean delete(String filePath) {
        return FileUtil.del(new File(filePath));
    }

    /**
     * 处理文件上传
     *
     * @param file        文件
     * @param filePath    文件路径
     * @param newFileName 新文件名称
     * @return 文件大小
     */
    public static Long uploadFileContinue(MultipartFile file, String filePath, String newFileName) {
        // 记录当前文件大小,用于判断文件是否上传完成
        long currentFileLength = 0;
        try {
            String fileName = file.getOriginalFilename();
            RandomAccessFile randomAccessfile;
            // 获取文件的扩展名
            String ext = "";
            if (!StringUtils.isEmpty(fileName)) {
                ext = fileName.substring(fileName.lastIndexOf(DOT));
            }
            File newFile = new File(filePath + newFileName + ext);
            if (!newFile.getParentFile().exists()) {
                newFile.getParentFile().mkdirs();
            }
            // 存在文件
            if (newFile.exists()) {
                randomAccessfile = new RandomAccessFile(newFile, "rw");
            } else {
                // 不存在文件,根据文件标识创建文件
                randomAccessfile = new RandomAccessFile(filePath + newFileName + ext, "rw");
            }
            // 开始文件传输
            InputStream in = file.getInputStream();
            if (randomAccessfile.length() < file.getInputStream().available()) {
                randomAccessfile.seek(randomAccessfile.length());
                in.skip(randomAccessfile.length());
                byte[] b = new byte[1024];
                int n;
                while ((n = in.read(b)) != -1) {
                    randomAccessfile.write(b, 0, n);
                }
            }
            currentFileLength = randomAccessfile.length();
            // 关闭文件
            closeRandomAccessFile(randomAccessfile);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return currentFileLength;

    }


    /**
     * 关闭随机访问文件
     *
     * @param randomAccessFile 随机访问的文件
     */
    private static void closeRandomAccessFile(RandomAccessFile randomAccessFile) {
        if (null != randomAccessFile) {
            try {
                randomAccessFile.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 转换PDF文件
     *
     * @param filePath 当前文件路径
     * @return PDF文件转换的全路径
     */
    public static String convertToPDF(String filePath, String targetPath) {
        log.info("filePath:{}", filePath);
        log.info("targetPath:{}", targetPath);
        String windowsPath = "D:/pdf/upload/";
        String command = null;
        String pdfPath = null;
        if (isLinux()) {
            command = "/usr/bin/libreoffice6.1 --headless --invisible --convert-to pdf " + filePath + " --outdir " + targetPath;
            pdfPath = targetPath +File.separator + changeSuffix(filePath, PDF);
        } else if (isWindows()) {
            command = "cmd /c start soffice --headless --invisible --convert-to pdf:writer_pdf_Export " + filePath + " --outdir " + targetPath;
            pdfPath = targetPath +File.separator+ changeSuffix(filePath, PDF);
        }
        System.out.println("pdf command:  " + command);
        Process exec = RuntimeUtil.exec(command);
        try {
            long startTime = System.currentTimeMillis();
            exec.waitFor();
            System.out.println("等待时长:" + (System.currentTimeMillis() - startTime));

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return pdfPath;
    }


    /**
     * 更改文件后缀
     *
     * @param filePath 当前文件路径
     * @param suffix   后缀
     * @return 更改后的文件名
     */
    public static String changeSuffix(String filePath, String suffix) {
        return getPrefix(filePath) + DOT + suffix;
    }


    /**
     * 判断当前OS的类型
     *
     * @return boolean
     */
    public static boolean isWindows() {
        return new OsInfo().isWindows();
    }

    /**
     * 判断当前OS的类型
     *
     * @return boolean
     */
    public static boolean isLinux() {
        return new OsInfo().isLinux();
    }

    /**
     * 根据文件名检查文件类型,忽略大小写
     *
     * @param fileName 文件名,例如hutool.png
     * @param extNames 被检查的扩展名数组,同一文件类型可能有多种扩展名,扩展名不带“.”
     * @return 是否是指定扩展名的类型
     */
    public static boolean isType(String fileName, String... extNames) {
        return FileNameUtil.isType(fileName, extNames);
    }

    /**
     * 获取文件名(包含后缀名)
     *
     * @return 文件名
     */
    public static String getName(String filePath) {
        return FileNameUtil.getName(filePath);
    }

    /**
     * 获取前缀名
     *
     * @return 文件前缀名
     */
    public static String getPrefix(String filePath) {
        return FileNameUtil.getPrefix(filePath);
    }

    /**
     * 获取后缀名(不包括 ".")
     *
     * @return 文件后缀名
     */
    public static String getSuffix(String filePath) {
        return FileNameUtil.getSuffix(filePath);
    }

    /**
     * 文件复制(不覆盖目标文件)
     *
     * @param srcPath  源文件
     * @param destPath 目标文件
     */
    public static File copy(String srcPath, String destPath) {
        return FileUtil.copy(srcPath, destPath, false);
    }

//    public static void main(String[] args) {
//        copy("C:\\Users\\lenovo\\Desktop\\123","C:\\Users\\lenovo\\Desktop\\456");
//    }


    /**
     * 取得OS的文件路径的分隔符(取自系统属性:<code>file.separator</code>)。
     *
     * <p>
     * 例如:Unix为<code>"/"</code>,Windows为<code>"\\"</code>。
     * </p>
     *
     * @return 属性值,如果不能取得(因为Java安全限制)或值不存在,则返回<code>null</code>。
     */
    public static String getFileSeparator() {
        return new OsInfo().getFileSeparator();
    }

    public static void downloadFile(HttpServletRequest request, HttpServletResponse response, InputStream inputStream, String fileName) {
        try (OutputStream os = response.getOutputStream();
             BufferedInputStream bis = new BufferedInputStream(inputStream);
             BufferedOutputStream bos = new BufferedOutputStream(os)) {
            // 处理下载文件名的乱码问题(根据浏览器的不同进行处理)
            if (request.getHeader("User-Agent").toLowerCase().indexOf("firefox") > 0) {
                fileName = new String(fileName.getBytes("GB2312"), "ISO-8859-1");
            } else {
                // 对文件名进行编码处理中文问题
                fileName = java.net.URLEncoder.encode(fileName, "UTF-8");// 处理中文文件名的问题
                fileName = new String(fileName.getBytes("UTF-8"), "GBK");// 处理中文文件名的问题
            }
            response.reset();
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/x-msdownload");// 不同类型的文件对应不同的MIME类型
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            int bytesRead = 0;
            byte[] buffer = new byte[4096];
            while ((bytesRead = bis.read(buffer)) != -1) {
                bos.write(buffer, 0, bytesRead);
                bos.flush();
            }
        } catch (Exception ex) {
            throw new RuntimeException(ex.getMessage());
        }
    }


    /**
     * 删除单个文件
     *
     * @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 path 被删除目录的文件路径
     * @return 目录删除成功返回true,否则返回false
     */
    public static boolean deleteDirectory(String path) {
        File dirFile = new File(path);
        // 如果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;
        }
    }


    public static void chown(String userName, String path) {
        String run = RuntimeUtils.execute("id -u " + userName);
        String run2 = RuntimeUtils.execute("id -g " + userName);
        RuntimeUtils.execute("chown -R " + run + ":" + run2 + " " + path);
    }


}

测试

http://47.94.226.83:9000/uploader/uploadFiles

 日志

 查看生成的预览文件

下载 看是否乱码  不乱码 这是我打的马赛克

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/548085.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

不敢妄谈K12教育

做为大学生的父亲&#xff1a;不敢妄谈孩子教育 大约10年前&#xff0c;写了一本教育书稿 找到一个出版社的编辑&#xff0c;被训了一通 打消了出书以及K12教育的念想 趣讲大白话&#xff1a;娘生九子&#xff0c;各有不同 【趣讲信息科技171期】 ****************************…

Vs+Qt+C++电梯调度控制系统

程序示例精选 VsQtC电梯调度控制系统 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<VsQtC电梯调度控制系统>>编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c;易读。…

PT100温度采集

1、信号采集的基本原理 PT100是将温度信号转换为电阻输出&#xff0c;其电阻值变化范围为0~200Ω。AD转换器只能对电压进行转换&#xff0c;无法采集直接采集温度&#xff0c;因此&#xff0c;需要一个1mA恒电流源给PT100供电&#xff0c;将电阻变化转换为电压变化。使用恒流源…

linux 安装 maven 3.8 版本

文章目录 1&#xff1a;maven 仓库官网 2、下载安装包 3、使用&#xff1a;Xftp 上传到你想放的目录 4、解压文件 ​编辑 5、配置环境变量 ​编辑 6、刷新 /etc/profile 文件 7、查看maven 版本 1&#xff1a;maven 仓库官网 Maven – Download Apache Mavenhttps://mave…

【C++】模板的一点简单介绍

模板 前言泛型编程函数模板概念格式函数模板的原理函数模板的实例化 类模板类模板的定义格式类模板的实例化 前言 这篇博客讲的是模板的一些基本知识&#xff0c;并没有那么深入&#xff0c;但是如果你是为了过期末考试而搜的这篇博客&#xff0c;我觉得下面讲的是够了的。 之…

简单分享线程池的设计

温故而知新&#xff0c;可以为师矣。 线程池是什么 线程池&#xff08;Thread Pool&#xff09;是一种基于池化思想管理线程的工具&#xff0c;经常出现在多线程服务器中&#xff0c;如MySQL。 池化思想&#xff0c;就是为了提高对资源的利用率&#xff0c;减少对资源的管理&a…

MySQL---空间索引、验证索引、索引特点、索引原理

1. 空间索引 MySQL在5.7之后的版本支持了空间索引&#xff0c;而且支持OpenGIS几何数据模型 空间索引是对空间数据类型的字段建立的索引&#xff0c;MYSQL中的空间数据类型有4种&#xff0c;分别是&#xff1a; 类型 含义 说明 Geometry 空间数据 任何一种空间类型 Poi…

HCIA-VRP系统

目录 一&#xff0c;什么是VRP VRP提供的功能&#xff1a; VRP文件系统&#xff1a; VRP存储设备&#xff1a; 设备初始化过程&#xff1a; 设备管理方式&#xff1a; 1&#xff0c;Web界面&#xff1a;可视化操作&#xff0c;通过http和https登录&#xff08;192.168.1.…

信息安全工程复习

目录 第二章 从口令系统说起 2.1 身份鉴别常见手段及例子 2.2 多因子认证 2.3 计时攻击 2.4 口令机制 2.5 假托和钓鱼 第三章 安全协议 3.1 认证协议 3.2 安全协议攻击 3.3 密钥分配协议 3.4 课后作业 第四章 访问控制 4.1 概念 4.2 控制访问三要素 4.3 控制访问…

Windows服务

参考地址&#xff1a;https://www.cnblogs.com/2828sea/p/13445738.html 1. 新建服务 2. 在 service 下 添加安装程序 会自动添加 修改这两个文件属性&#xff1a; serviceInstaller1&#xff1a; DelayedAutoStart:是否自动启动Descrition:介绍服务&#xff08;自定义&…

chatgpt赋能Python-python3_图片处理

Python3图片处理&#xff1a;简单高效的图像处理工具 Python3作为一种高级编程语言&#xff0c;在科学、金融、工程等领域中广受欢迎。它具有简洁的语法、快速的开发速度、多样化的应用场景等特点。其中&#xff0c;Python3在图像处理方面也非常出色&#xff0c;本文将介绍Pyt…

pg事务:事务的处理

事务的处理 事务块 从事务形态划分可分为隐式事务和显示事务。隐式事务是一个独立的SQL语句&#xff0c;执行完成后默认提交。显示事务需要显示声明一个事务&#xff0c;多个sql语句组合到一起称为一个事务块。 事务块通过begin&#xff0c;begin transaction&#xff0c;st…

【学习日记2023.5.20】 之 菜品模块完善

文章目录 3. 功能模块完善之菜品模块3.1 公共字段自动填充3.1.1 问题分析3.1.2 实现思路3.1.3 代码开发1.3.1 步骤一1.3.2 步骤二1.3.3 步骤三 3.1.4 功能测试3.1.5 提交代码 3.2 新增菜品3.2.1 需求分析与设计3.2.2 代码开发3.2.2.1 文件上传实现3.2.2.2 新增菜品实现 3.2.3 功…

pg事务:快照

pg中的快照 快照&#xff08;snapshot&#xff09;是记录数据库当前瞬时状态的一个数据结构。pg数据库的快照保存当前所有活动事务的最小事务ID、最大事务ID、当前活跃事务列表、当前事务的command id等 快照数据保存在SnapshotData结构体类型中&#xff0c;源码src/include/u…

PyQt5桌面应用开发(16):定制化控件-QPainter绘图

本文目录 PyQt5桌面应用系列画画图&#xff0c;喝喝茶QPainter和QPixmapQPixmapQPainter绘制事件 一个魔改的QLabelCanvas类主窗口主程序&#xff1a; 总结 PyQt5桌面应用系列 PyQt5桌面应用开发&#xff08;1&#xff09;&#xff1a;需求分析 PyQt5桌面应用开发&#xff08;2…

深入了解vector

vector 1. vector的介绍及使用1.1 vector的介绍1.2 vector的使用1.2.1 vector的定义&#xff08;(constructor)构造函数声明&#xff09;1.2.2 vector iterator 的使用1.2.3 vector Capacity1.2.4 vector Modifiers1.2.4 vector 迭代器失效问题 2. vector模拟实现 1. vector的介…

快速排序的三种方法

今日复习了一下快速排序的算法。 hoare法 快速排序由Hoare在1960年提出。它的基本思想是&#xff1a;通过排序将需要排序的数据分割成独立的两部分&#xff0c;左边的所有数据都比右边的小&#xff0c;然后再按此方法对这两部分数据分别进行快速排序递归&#xff0c;使其变成有…

时间序列预测 | 基于秃鹰算法优化BP神经网络(BES-BP)的时间序列预测,matlab代码

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 基于秃鹰算法优化BP神经网络(BES-BP)的时间序列预测,matlab代码 评价指标包括:R2、MAE、MSE、RMSE等,代码质量极高,方便学习和替换数据。 部分源码 %% 清空环境变量 warning off % 关闭报警信息…

BurpSuite—-Spider模块(蜘蛛爬行)

本文主要介绍BurpSuite—-Spider模块(蜘蛛爬行)的相关内容 关于BurpSuite的安装可以看一下之前这篇文章&#xff1a; http://t.csdn.cn/0Qw2n 一、简介 Burp Spider 是一个映射 web 应用程序的工具。它使用多种智能技术对一个应用程序的内容和功能进行全面的清查。 Burp Spi…

基于Qt+FFmpeg的视频监控系统

github源码 需求分析 假设一个业务场景&#xff1a;每个员工工位旁有两个网络摄像头。老板需要一个员工监控软件&#xff0c;在上班时软件可以拉取RTSP视频流&#xff0c;也可以随时录制视频。这样老板就可以知道谁在摸鱼了 ◕‿◕ 为防有人上纲上线&#xff0c;在此特别声明…