后端oss存储(完整版) [不同环境下测试通过] 以及 解决删除本地文件显示被占用问题

目录

整体逻辑思路:

第一步 : 发送请求

了解apipost/postman上传文件方式body -> multipart/form-data

apipost快速上手-> 链接

第二步: controller层 请求

第三步: 实现类 业务逻辑

第四步: [oss上传,是一个/链接,包含回调异常和封装的util包 ]

第五步:  上传oss成功 返回了url 

第六步:  删除本地文件, 突遇问题

逻辑: 无论上传的成不成功 ,都删除本地文件  返回状态

6.1 ->  把升级版的删除 放到 ossutils 的return里面

看第七步----> 解决办法

第七步: 发现文件被占用问题 并解决

文件删除util包, 解决文件被占用问题 

调用gc的几种方式

第8步: 补充:  想要删除文件夹

方法 是循环删除文件 后删除文件夹 


整体逻辑思路:

文件->前端发送请求 -> 后端upload->本地文件 -> oss ->无论成不成功 删除本地 返回状态

难点: 删除本地文件的时候 明明显示文件路径存在却无法删除问题

第一步 : 发送请求

了解apipost/postman上传文件方式body -> multipart/form-data

apipost快速上手-> 链接

Postman,ApiPost, Idea httpclient tools, 替代swagger,零侵入 接口文档生成 及几种后端测试方式

后端oss存储(完整版) [不同环境下测试通过] 以及 解决删除本地文件显示被占用问题_第1张图片

第二步: controller层 请求

后端oss存储(完整版) [不同环境下测试通过] 以及 解决删除本地文件显示被占用问题_第2张图片

 @RequestMapping(value = "/uploads", method = RequestMethod.POST)
    @ResponseBody
    public SystemResult uploads(MultipartFile[] file, HttpSession session) {

        log.debug("===> 开启文件上传 <===");

        return uploadService.fileUploadCtrl(file,session);
    }

第三步: 实现类 业务逻辑

/**
 * @Author pzy
 * @Version 0.1.0
 */
@Service
@Slf4j
public class OSSAddServiceImpl implements OSSAddService {

    //    @Value("${file.uploadFolder}")
    private static final String uploadPath = "D:/usr/local/src/images";//windows
    //private static final String uploadPath = "/usr/local/src/images";//linux


    @Override
    public Result OSSAddImg(MultipartFile[] file, HttpSession session) {
        //上传目录地址
        String uploadDir = uploadPath;
        log.debug(uploadPath);

        //(最新修改)如果目录不存在,自动创建文件夹(修复)

        if (!createFile(1, new File(uploadDir), false)) {
            log.error("-------> 自动创建文件或文件夹失败!!! <--------");
        }


        String suffix = null;
        String fileName = null;

        //  HashMap hashMap = new HashMap();
        try {
            //遍历文件数组执行上传(多文件上传需要)
            for (int i = 0; i < file.length; i++) {
                if (file[i] != null) {
                    log.debug("开始上传文件.......");
                    //调用上传方法
                    suffix = file[i].getOriginalFilename().substring(file[i].getOriginalFilename().lastIndexOf(".")); //后缀名
                    fileName = UUID.randomUUID() + suffix;
                    IOUtils.copy(file[i].getInputStream(), new FileOutputStream(uploadDir + "\\" + fileName));
                    //file[i].transferTo(new File(uploadDir+"\\"+fileName));
                    log.debug("上传" + uploadDir + "\\" + fileName + "文件成功!");
                }
            }
            log.debug("上传结束!所有文件上传文件至:" + uploadDir);
            System.out.printf("文件名->%s\n", fileName);


        } catch (Exception e) {
            //打印错误堆栈信息
            e.printStackTrace();
            log.error("上传文件失败,请检查后重试!!!");
            //  hashMap.put("uploadMessage", "上传失败");


            return Result.fail(String.valueOf(500), "上传失败");
        }

        log.debug(fileName + ", " + (uploadPath + "\\" + fileName));

        //上传oss 没有进一步封装
        Result systemResult = OSSUtils.OSSUpload(fileName, uploadPath);

//        String path = (uploadPath + "\\" + fileName);
//        System.out.println(path);

        return systemResult;
//        return Result.success(200);

    }

    /**
     * 判断文件是否存在,不存在就创建
     *
     * @param file
     */
    public static boolean createFile(int type, File file, Boolean flag) {
        if (type == 1) {
            if (!file.exists()) {
                return file.mkdirs();
            }
        }
//其他就是0 文件及目录创建(存在bug)
        if (file.exists()) {
            log.debug("文件及相关路径存在!!!");
        } else {
            log.info("文件不存在 ,创建文件以及文件夹 ...");
            //getParentFile() 获取上级目录(包含文件名时无法直接创建目录的)
            if (!file.getParentFile().exists()) {
                log.info("文件及其路径不存在, 创建路径文件!!!");
                //创建层级目录
                if (!file.getParentFile().mkdirs()) {
                    return false;
                }
            }
            if (flag) {
                try {
                    //上层目录创建文件
                    log.info("文件夹创建开启,在上层目录下创建文件夹");
                    if (file.createNewFile()) {
                        return false;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return true;
    }


}

注意这个:  

与application.properties对应 

 如果是微服务可以在配置中心修改

内容必须与file.uploadFolder一致  防止空指针可以添加默认值  这里我没添加

第四步: [oss上传,是一个/链接,包含回调异常和封装的util包 ]

注意到没有: [最近更新 回调存在的问题也包含在内]

SystemResult systemResult = OSSUtils.OSSUpload(fileName, uploadPath);

这个util包没有  自己封装的 嘿嘿

下面这篇文章中 完整的ossUtils包(可以直接测通)

(java)oss 文件(视频)上传, 获取回调中的url, 官网地址_pingzhuyan的博客

第五步:  上传oss成功 返回了url 

https://*.oss.......mp4 

尝试一下是否可以观看  如果是私有的 需要粘全查看, 公共的直接可以看

将url进行记录保存(丢失的可以去阿里云控制台上操作)

第六步:  删除本地文件, 突遇问题

逻辑: 无论上传的成不成功 ,都删除本地文件  返回状态

注意: 文章开头说的难点出现了 

先在本地测试 路径写死, 测试删除文件  成功

 public static void main(String[] args) {
        String path ="D:\\software\\workspaceAll\\company\\UseSDK\\alipayctrl\\src\\main\\resources\\static\\pzy\\aaa.txt";

        File file = new File(path);
        boolean delete = file.delete();
        System.out.println(delete);
        
    }

6.1 ->  把升级版的删除 放到 ossutils 的return里面

也就是oss上传 后(无论成功失败) 都执行删除方法

但是惊喜的发现 file.exist 是true  delete失败 

说明文件删除不了, 首先考虑文件是不是被占用了,调用gc  

emm  不是每次执行都会成功 , 依旧存在失败情况

由于 gc不是说执行就执行的 只能通知gc 

没办法 只能写个循环 等待gc删除后返回true 退出循环(欢迎大佬指导...这是我能想到的办法)

看第七步----> 解决办法

第七步: 发现文件被占用问题 并解决

文件删除util包, 解决文件被占用问题 

path参数 是路径的意思(删除)

package sso.util;

import lombok.extern.slf4j.Slf4j;

import java.io.File;

/**
 * @Author pzy
 * @Version 0.1.0
 */
@Slf4j
public class FileIOUtils {

    /**
     * @param path
     */
    public static boolean fileGCDelete(String path) {
        boolean flag = false;
        File file1 = new File(path);
        if (file1.exists()) {
            flag = file1.delete();
            try {
                for (; ;) {
                    if (!flag) {
                        System.gc();    //回收资源
                        flag = file1.delete();
                    }
                    if (flag) break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            log.debug("路径存在" + flag);
        }
        return flag;
    }
}

调用gc的几种方式

System.gc();
// 或者下面,两者等价
Runtime.getRuntime().gc();
//这个跟System.gc相同, 都是等效于第二个
java.lang.management.MemoryMXBean.gc()

第8步: 补充:  想要删除文件夹

方法 是循环删除文件 后删除文件夹 

代码: [解决方式有多种,这种是递归]

package *;

import java.io.File;

public class PackageDelete {
    public static void main(String[] args) {
        deleteFileAndFoder("../yang");
    }
    static void deleteFileAndFoder(String path){
            File f=new File(path);
            if(f.isDirectory()){//如果是目录,先递归删除
                String[] list=f.list();
                for(int i=0;i

[除了上传oss的代码demo 其他完成了,自己思路, 做的可能不好,多多包涵 ]  pzy

你可能感兴趣的:(#,第三方服务,java,oss,gc,MultipartFile[],Apipost)