阿里对象存储OSS的封装

1.配置类

   @Bean
    public OSS ossClient(){
        // 创建OSSClient实例。
        CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKey, secretKey);
        // 创建ClientBuilderConfiguration。
        // ClientBuilderConfiguration是OSSClient的配置类,可配置代理、连接超时、最大连接数等参数。
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        // 设置是否支持CNAME。CNAME用于将自定义域名绑定到目标Bucket。
        conf.setSupportCname(true);
        // 设置Socket层传输数据的超时时间,默认为50000毫秒。
        conf.setSocketTimeout(10000);
        // 设置建立连接的超时时间,默认为50000毫秒。
        conf.setConnectionTimeout(10000);
        // 设置失败请求重试次数,默认为3次。
        conf.setMaxErrorRetry(5);
        return new OSSClientBuilder().build(endpoint, credentialsProvider, conf);
    }

2.接口


public interface FileUploadService {


    /**
     * 将路径变为共享路径
     * @param url
     * @return
     */
    String fileUrlToShareUrl(String url);

    /**
     * 文件是否存在
     *
     * @param url
     * @return
     */
    boolean fileIsExist(String url);


    /**
     * @param url
     * @return
     * @throws HttpStatusException
     */
    boolean isTemporaryFile(String url) throws HttpStatusException;

    /**
     * 上传到临时文件里
     *
     * @param name
     * @param stream
     * @return
     */
    String uploadTempFile(String name, InputStream stream);

    /**
     * 移动一个文件
     *
     * @param oldUrl
     * @param newUrl
     * @throws HttpStatusException
     */
    void moveFile(String oldUrl, String newUrl) throws HttpStatusException;


    /**
     * 删除一个文件
     *
     * @param url
     * @return
     */
    boolean delFile(String url);

    /**
     * 校验文件名
     *
     * @param originalFilename
     * @return
     * @throws HttpStatusException
     */
    String validateFileName(String originalFilename) throws HttpStatusException;


    /**
     * 从url按一定规则取出文件名
     *
     * @param url
     * @return
     * @throws CodeException
     */
    String getUrlFileName(String url) throws CodeException;

    /**
     * 将临时文件路径转化为真实文件路径
     *
     * @param url    文件路径
     * @param prefix 文件名前面的路径
     * @return
     */
    String urlChangeToTruthUrl(String url, String prefix) throws CodeException;


    /**
     * 上传文件
     *
     * @param url
     * @param stream
     */
    void uploadFile(String url, InputStream stream);

    /**
     * 下载文件
     *
     * @param fileName
     * @param url
     * @param response
     * @throws IOException
     */
    void downLoadFile(String fileName, String url, HttpServletResponse response) throws IOException, CodeException;


    /**
     * 处理事务提交后的文件 可删除 可添加
     * <p>
     * value 为null删除
     * value 不为null添加
     *
     * @param fileDtoMap
     */
    void handlerFile(Map<String, ? extends FileDto> fileDtoMap);

    /**
     * 返回 处理完毕的url 要么是和原来一样,要么就是新的修改过后的文件
     *
     * @param resultUrlMap
     * @param filePrefix   文件前缀
     * @return
     */
    List<FileDto> handlerUpdateFile(Map<String, FileDto> resultUrlMap, List<FileDto> sourceFileList, List<FileDto> newFileList, String filePrefix) throws CodeException;


    /**
     * 还原文件路径
     * @param fileDtoList
     * @throws CodeException
     */
    void removeFileUrlHost(List<FileDto> fileDtoList) throws CodeException;

}

3.实现

public class OssUploadServiceImpl implements FileUploadService {

    private static final String truthDir = "truth/";
    private static final String temporaryDir = "temporary/";
    private final OSS ossClient;
    private static final Logger log = LoggerFactory.getLogger(OssUploadServiceImpl.class);
    private final String bucketName;


    public OssUploadServiceImpl(OSS ossClient, String bucketName) {
        this.ossClient = ossClient;
        this.bucketName = bucketName;
    }



    public void list(String prefix) {

        // 列举文件。如果不设置keyPrefix,则列举存储空间下的所有文件。如果设置keyPrefix,则列举包含指定前缀的文件。
        ObjectListing objectListing = ossClient.listObjects(bucketName, prefix);
        List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
        for (OSSObjectSummary s : sums) {
            System.out.println("==============");
            System.out.println("\t" + s.getKey());
            System.out.println(s);
            System.out.println(s.getType());
            System.out.println(s.getETag());
            System.out.println("==============");
        }


    }

    /**
     * 把文件路径变为共享路径
     * @param url
     * @return
     */
    @Override
    public String fileUrlToShareUrl(String url) {

        try {

            if (!fileIsExist(url)){
                return null;
            }

            // 指定生成的签名URL过期时间,单位为毫秒。本示例以设置过期时间为1小时为例。
            Date expiration = new Date(new Date().getTime() + 3600 * 1000L);

            // 生成签名URL。
            GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, url, HttpMethod.GET);
            // 设置过期时间。
            request.setExpiration(expiration);

            // 通过HTTP GET请求生成签名URL。
            URL signedUrl = ossClient.generatePresignedUrl(request);

            return  signedUrl.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  null;
    }

    @Override
    public boolean fileIsExist(String url) {
        try {
            if (StringUtils.strIsBlank(url)){
                return false;
            }

            return ossClient.doesObjectExist(bucketName, url);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }



    @Override
    public boolean isTemporaryFile(String url) throws HttpStatusException {
        if (url.startsWith(temporaryDir)) {
            return true;
        } else if (url.startsWith(truthDir)) {
            return false;
        } else {
            throw new HttpStatusException(HttpStatus.BAD_REQUEST, com.coweixin.heatsource.common.ErrorCode.PARAM_ERROR, "文件路径不合法 url=" + url);
        }
    }

    @Override
    public String uploadTempFile(String name, InputStream stream) {
        String url = temporaryDir + UUID.randomUUID().toString() + name;
        uploadFile(url, stream);
        return url;
    }

    @Override
    public void moveFile(String oldUrl, String newUrl) throws HttpStatusException {

        if (!fileIsExist(oldUrl)) {
            log.error("临时文件不存在 一个文件上传失败: url={} ", oldUrl);
            return;
        }

        // 拷贝文件。
        try {
            ossClient.copyObject(bucketName, oldUrl, bucketName, newUrl);

            delFile(oldUrl);
        } catch (Exception e) {
          e.printStackTrace();
        }

    }

    @Override
    public boolean delFile(String url) {

        // 删除文件或目录。如果要删除目录,目录必须为空。
        try {

            if (!fileIsExist(url)) {
                log.error("文件不存在 一个文件删除失败: url={} ", url);
                return false;
            }


            ossClient.deleteObject(bucketName, url);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public String validateFileName(String originalFilename) throws HttpStatusException {
        if (originalFilename == null || originalFilename.contains("/") || originalFilename.contains(File.separator) || originalFilename.startsWith("*") || originalFilename.startsWith("&") || originalFilename.startsWith("?") || originalFilename.startsWith("$")) {
            throw new HttpStatusException(HttpStatus.BAD_REQUEST, com.coweixin.heatsource.common.ErrorCode.PARAM_ERROR, "文件名不能为空,且不能以/ * & ? $ 开头");
        }

        String trimName = originalFilename.trim();

        if (!trimName.contains(".")) {
            throw new HttpStatusException(HttpStatus.BAD_REQUEST, com.coweixin.heatsource.common.ErrorCode.PARAM_ERROR, "文件名必须包含扩展名");
        }

        if (trimName.length() <= 3 || trimName.length() >= 30) {
            throw new HttpStatusException(HttpStatus.BAD_REQUEST, com.coweixin.heatsource.common.ErrorCode.PARAM_ERROR, "文件名长度不得小于3或超过30");
        }

        return trimName;
    }

    @Override
    public String getUrlFileName(String url) throws CodeException {
        try {
            List<String> list = StrSplitter.splitPath(url);
            if (!list.isEmpty()) {
                String endUrl = list.get(list.size() - 1);
                return endUrl.substring(36);
            }
            throw new RuntimeException();
        } catch (Exception e) {
            throw new CodeException(com.coweixin.common.exception.ErrorCode.PARAM_FORMAT_ERR, "文件路径不合法 url=" + url);
        }
    }

    @Override
    public String urlChangeToTruthUrl(String url, String prefix) throws CodeException {
        String urlFileName = getUrlFileName(url);
        return truthDir + prefix + UUID.randomUUID() + urlFileName;
    }

    /**
     * 上传文件
     *
     * @param url
     * @param stream
     */
    @Override
    public void uploadFile(String url, InputStream stream) {
        try {
            ossClient.putObject(new PutObjectRequest(bucketName, url, stream));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (stream != null) {
                    stream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void downLoadFile(String fileName, String url, HttpServletResponse response) throws IOException, CodeException {
        // ossObject包含文件所在的存储空间名称、文件名称、文件元数据以及一个输入流。
        if (!fileIsExist(url)){
            throw new CodeException(ErrorCode.PARAM_FORMAT_ERR,"文件不存在");
        }

        OSSObject ossObject = ossClient.getObject(bucketName, url);
        fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString());
        response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
        try (InputStream fis =  ossObject.getObjectContent()) {
            IOUtils.copy(fis, response.getOutputStream());
        }
    }

    @Override
    public void handlerFile(Map<String, ? extends FileDto> fileDtoMap) {
        for (Map.Entry<String, ? extends FileDto> entry : fileDtoMap.entrySet()) {

            try {

                String oldUrl = entry.getKey();
                FileDto value = entry.getValue();
                if (value != null) {
                    //value不为空为添加
                    this.moveFile(oldUrl, value.getUrl());
                } else {
                    //否则删除
                    this.delFile(oldUrl);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }


        }
    }

    @Override
    public List<FileDto> handlerUpdateFile(Map<String, FileDto> resultUrlMap, List<FileDto> sourceFileList, List<FileDto> newFileList, String filePrefix) throws CodeException {
        if (sourceFileList == null || sourceFileList.isEmpty()) {
            //原来的是空集或空,那么可以放心大胆的添加操作
            for (FileDto fileDto : newFileList) {
                String url = fileDto.getUrl();
                String newTruthUrl = urlChangeToTruthUrl(url, filePrefix);
                fileDto.setUrl(newTruthUrl);
                resultUrlMap.put(url, fileDto);
            }
        } else if (newFileList == null || newFileList.isEmpty()) {

            //新来的是空集或空,那么可以放心大胆的删除操作
            for (FileDto fileDto : sourceFileList) {
                String url = fileDto.getUrl();
                resultUrlMap.put(url, null);//
            }
        } else {
            //两个都不为空
            for (FileDto fileDto : sourceFileList) {
                if (newFileList.contains(fileDto)) {
                    //新的包含了,就什么都不操作
                } else {
                    //新的不包含就删除
                    resultUrlMap.put(fileDto.getUrl(), null);
                }
            }
            newFileList.stream()
                    .filter(fileDto -> !sourceFileList.contains(fileDto))
                    .forEach(fileDto -> {
                        try {
                            String url = fileDto.getUrl();
                            String newTruthUrl = urlChangeToTruthUrl(url, filePrefix);
                            fileDto.setUrl(newTruthUrl);
                            resultUrlMap.put(url, fileDto);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    });
        }

        return newFileList;


    }

    @Override
    public void removeFileUrlHost(List<FileDto> fileDtoList) throws CodeException {
        if (fileDtoList==null||fileDtoList.isEmpty() ) {
            return;
        }
        for (FileDto fileDto : fileDtoList) {
            try {
                String url = fileDto.getUrl();
                if (StringUtils.strIsBlank(url)){
                    throw new CodeException(ErrorCode.PARAM_FORMAT_ERR,"路径不能为空");
                }
                String decodeUrl = URLDecoder.decode(url, StandardCharsets.UTF_8.toString());

                String regex = "^https?://[^/]+/(.*?)(\\?[^#]*)?$";
                Pattern pattern = Pattern.compile(regex);
                Matcher matcher = pattern.matcher(decodeUrl);
                if (matcher.find()) {
                    // 获取匹配的路径部分
                    url = matcher.group(1);
                    fileDto.setUrl(url);
                }
            } catch (UnsupportedEncodingException e) {
               e.printStackTrace();
            }
        }
    }
}

4.本地实现

public class LocalUploadServiceImpl implements FileUploadService {
    private static final String rootDir = "C:/environment/nginx-1.26.1/html/static/";
    private static final String truthDir = "truth/";
    private static final String temporaryDir = "temporary/";
    private static final Logger log = LoggerFactory.getLogger(LocalUploadServiceImpl.class);
    private static final  String serverAddrHost = "http://192.168.202.57/";


    @Override
    public String fileUrlToShareUrl(String url) {
        return serverAddrHost+url;
    }

    @Override
    public boolean fileIsExist(String url) {
        return new File(rootDir + url).exists();
    }

    public File getFile(String url) {
        return new File(rootDir + url);
    }

    @Override
    public boolean isTemporaryFile(String url) throws HttpStatusException {
        if (url.startsWith(temporaryDir)) {
            return true;
        } else if (url.startsWith(truthDir)) {
            return false;
        } else {
            throw new HttpStatusException(HttpStatus.BAD_REQUEST, ErrorCode.PARAM_ERROR, "文件路径不合法 url=" + url);
        }
    }

    @Override
    public String uploadTempFile(String name, InputStream stream) {
        String url = UUID.randomUUID().toString() + name;

        FileWriter fileWriter = new FileWriter(rootDir + temporaryDir + url);

        fileWriter.writeFromStream(stream);

        return temporaryDir + url;
    }


    @Override
    public void moveFile(String oldUrl, String newUrl) throws HttpStatusException {
        File src = getFile(oldUrl);
        if (!src.exists()) {
            log.error("临时文件不存在 一个文件上传失败: url={} ", oldUrl);
            return;
        }
        File target = new File(rootDir + newUrl);
        FileUtil.move(src, target, true);
    }

    @Override
    public boolean delFile(String url) {
        File file = new File(rootDir + url);

        boolean exists = file.exists();

        boolean isFile = file.isFile();

        if (!exists) {
            log.error("删除的文件不存在 url={}", url);
            return false;
        }

        if (!isFile) {
            log.error("删除的不是文件 url={}", url);
            return false;
        }

        boolean del = FileUtil.del(file);

        return del;
    }


    @Override
    public String validateFileName(String originalFilename) throws HttpStatusException {
        if (originalFilename == null || originalFilename.contains("/") || originalFilename.contains(File.separator) || originalFilename.startsWith("*") || originalFilename.startsWith("&") || originalFilename.startsWith("?") || originalFilename.startsWith("$")) {
            throw new HttpStatusException(HttpStatus.BAD_REQUEST, ErrorCode.PARAM_ERROR, "文件名不能为空,且不能以/ * & ? $ 开头");
        }

        String trimName = originalFilename.trim();

        if (!trimName.contains(".")) {
            throw new HttpStatusException(HttpStatus.BAD_REQUEST, ErrorCode.PARAM_ERROR, "文件名必须包含扩展名");
        }

        if (trimName.length() <= 3 || trimName.length() >= 30) {
            throw new HttpStatusException(HttpStatus.BAD_REQUEST, ErrorCode.PARAM_ERROR, "文件名长度不得小于3或超过30");
        }

        return trimName;
    }



    @Override
    public String getUrlFileName(String url) throws CodeException {
        try {
            List<String> list = StrSplitter.splitPath(url);
            if (!list.isEmpty()) {
                String endUrl = list.get(list.size() - 1);
                return endUrl.substring(36);
            }
            throw new RuntimeException();
        } catch (Exception e) {
            throw new CodeException(com.coweixin.common.exception.ErrorCode.PARAM_FORMAT_ERR, "文件路径不合法 url=" + url);
        }
    }


    @Override
    public String urlChangeToTruthUrl(String url, String prefix) throws CodeException {
        String urlFileName = getUrlFileName(url);
        return truthDir + prefix + UUID.randomUUID() + urlFileName;
    }

    @Override
    public void uploadFile(String url, InputStream stream) {
        FileWriter fileWriter = new FileWriter(rootDir + url);
        fileWriter.writeFromStream(stream);
    }

    @Override
    public void downLoadFile(String fileName, String url, HttpServletResponse response) throws IOException {
        fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString());
        response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
        try (FileInputStream fis = new FileInputStream(rootDir + url)) {
            IOUtils.copy(fis, response.getOutputStream());
        }
    }



    @Override
    public void handlerFile(Map<String,? extends FileDto> fileDtoMap) {
        for (Map.Entry<String, ? extends FileDto> entry : fileDtoMap.entrySet()) {

            try {

                String oldUrl = entry.getKey();
                FileDto value = entry.getValue();
                if (value != null) {
                    //value不为空为添加
                    this.moveFile(oldUrl, value.getUrl());
                } else {
                    //否则删除
                    this.delFile(oldUrl);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }


        }
    }

    /**
     * 返回的是可以持久化的 fileDto集合对象
     *
     * @param resultUrlMap
     * @param sourceFileList
     * @param newFileList
     * @param filePrefix     文件前缀
     * @return
     * @throws CodeException
     */
    @Override
    public List<FileDto> handlerUpdateFile(Map<String, FileDto> resultUrlMap, List<FileDto> sourceFileList, List<FileDto> newFileList, String filePrefix) throws CodeException {
        if (sourceFileList == null || sourceFileList.isEmpty()) {
            //原来的是空集或空,那么可以放心大胆的添加操作
            for (FileDto fileDto : newFileList) {
                String url = fileDto.getUrl();
                String newTruthUrl = urlChangeToTruthUrl(url, filePrefix);
                fileDto.setUrl(newTruthUrl);
                resultUrlMap.put(url, fileDto);
            }
        } else if (newFileList == null || newFileList.isEmpty()) {

            //新来的是空集或空,那么可以放心大胆的删除操作
            for (FileDto fileDto : sourceFileList) {
                String url = fileDto.getUrl();
                resultUrlMap.put(url, null);//
            }
        } else {
            //两个都不为空
            for (FileDto fileDto : sourceFileList) {
                if (newFileList.contains(fileDto)) {
                    //新的包含了,就什么都不操作
                } else {
                    //新的不包含就删除
                    resultUrlMap.put(fileDto.getUrl(), null);
                }
            }
            newFileList.stream()
                    .filter(fileDto -> !sourceFileList.contains(fileDto))
                    .forEach(fileDto -> {
                        try {
                            String url = fileDto.getUrl();
                            String newTruthUrl = urlChangeToTruthUrl(url, filePrefix);
                            fileDto.setUrl(newTruthUrl);
                            resultUrlMap.put(url, fileDto);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    });
        }

        return newFileList;


    }




    @Override
    public void removeFileUrlHost(List<FileDto> fileDtoList) throws CodeException {
        if (fileDtoList==null||fileDtoList.isEmpty() ) {
            return;
        }
        for (FileDto fileDto : fileDtoList) {
            String url = fileDto.getUrl();
            if (StringUtils.strIsBlank(url)){
                throw new CodeException(ErrorCode.PARAM_FORMAT_ERR,"路径不能为空");
            }
            String regex = "^https?://[^/]+/(.*)";
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(url);
            if (matcher.find()) {
                // 获取匹配的路径部分
                url = matcher.group(1);
                fileDto.setUrl(url);
            }
        }


    }


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值