springBoot集成华为云obs对象存储

springBoot集成华为云obs对象存储

一、准备工作:华为云平台注册账号

  1. 获取 AK、SK
  2. 获取 endPoint
  3. 创建桶

二、springBoot项目集成obs服务器

  1. spring-boot的pom.xml中添加组件【这里使用的是v=3.21.8】
<dependency>
    <groupId>com.huaweicloud</groupId>
    <artifactId>esdk-obs-java</artifactId>
    <version>3.21.8</version>
</dependency>

<!--
必须制定okhttp3的最新版本号,
否则会出现java.lang.NoSuchMethodError: okhttp3.RequestBody.create
-->
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.9.3</version>
</dependency>
<!--
必须指定与okhttp相匹配的okio的版本,否则会出现okio和okhttp的包冲突问题
java.lang.NoSuchMethodError: kotlin
-->
<dependency>
    <groupId>com.squareup.okio</groupId>
    <artifactId>okio</artifactId>
    <version>2.8.0</version>
</dependency>
  1. spring-boot的application.properties文件中配置
#华为云obs配置
hwyun.obs.accessKey=****
hwyun.obs.securityKey=***
hwyun.obs.endPoint=***
hwyun.obs.bucketName=***
  1. 创建对应的HweiOBSConfig参数配置类
package com.elink;

import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import lombok.Data;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import java.text.SimpleDateFormat;
import java.util.Date;

@Data
@Configuration
public class HweiOBSConfig {

    private static final Logger log = Logger.getLogger(HweiOBSConfig.class);

    /**
     * 访问密钥AK
     */
    @Value("${hwyun.obs.accessKey}")
    private String accessKey;

    /**
     * 访问密钥SK
     */
    @Value("${hwyun.obs.securityKey}")
    private String securityKey;

    /**
     * 终端节点
     */
    @Value("${hwyun.obs.endPoint}")
    private String endPoint;

    /**
     * 桶
     */
    @Value("${hwyun.obs.bucketName}")
    private String bucketName;

    /**
     * @Description 获取OBS客户端实例
     * @return: com.obs.services.ObsClient
     */
    public ObsClient getInstance() {
        return new ObsClient(accessKey, securityKey, endPoint);
    }

    /**
     * @Description 销毁OBS客户端实例
     * @param: obsClient
     */
    public void destroy(ObsClient obsClient){
        try {
            obsClient.close();
        } catch (ObsException e) {
            log.error("obs执行失败", e);
        } catch (Exception e) {
            log.error("执行失败", e);
        }
    }

    /**
     * @Description 微服务文件存放路径
     * @return: java.lang.String
     */
    public static String getObjectKey() {
        // 项目或者服务名称 + 日期存储方式
        return "Hwei" + "/" + new SimpleDateFormat("yyyy-MM-dd").format(new Date() )+ "/";
    }
}

  1. 创建业务层接口
package com.elink.license.service;

import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;
import java.util.List;

/**
 * 华为云OBS服务接口
 */
public interface IHweiYunOBSService {

    /**
     * @Description 删除文件
     * @param: objectKey 文件名
     * @return: boolean 执行结果
     */
    boolean delete(String objectKey);
    boolean deleteFileByPath(String objectKey);

    /**
     * @Description 批量删除文件
     * @param: objectKeys 文件名集合
     * @return: boolean 执行结果
     */
    boolean delete(List<String> objectKeys);

    /**
     * @Description 上传文件
     * @param: uploadFile 上传文件
     * @param: objectKey 文件名称
     * @return: java.lang.String url访问路径
     */
    String fileUpload(MultipartFile uploadFile, String objectKey);
    String uploadFileByte(byte data[], String objectKey);
    String uploadFile(File file);

    /**
     * @Description 文件下载
     * @param: objectKey
     * @return: java.io.InputStream
     */
    InputStream fileDownload(String objectKey);
}

package com.elink.license.service.impl;

import com.elink.HweiOBSConfig;
import com.elink.base.util.PropertiesUtil;
import com.elink.license.service.IHweiYunOBSService;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.*;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

/**
 * 华为云OBS服务业务层
 */

@Service
public class HweiYunOBSServiceImpl implements IHweiYunOBSService {

    private static final Logger log = Logger.getLogger(HweiYunOBSServiceImpl.class);


    @Autowired
    private HweiOBSConfig hweiOBSConfig;

    @Override
    public boolean delete(String objectKey) {
        ObsClient obsClient = null;
        try {
            // 创建ObsClient实例
            obsClient = hweiOBSConfig.getInstance();
            // obs删除
            obsClient.deleteObject(hweiOBSConfig.getBucketName(), objectKey);
        } catch (ObsException e) {
            log.error("obs[delete]删除保存失败", e);
        } finally {
            hweiOBSConfig.destroy(obsClient);
        }
        return true;
    }

    @Override
    public boolean deleteFileByPath(String path) {
        //path:https://wwwbak.obs.ap-southeast-1.myhuaweicloud.com/uploadFiles/xiehui/yongjiu/fujian/wode.jpg
        ObsClient obsClient = null;
        try {
            // 创建ObsClient实例
            obsClient = hweiOBSConfig.getInstance();

            String file_http_url = PropertiesUtil.readValue("file_http_url");

            File file = new File(path);
            String key = file.getName();//wode.jpg

            //realPath : uploadFiles/xiehui/yongjiu/fujian
            String realPath = path.replace(file_http_url, "");
            realPath = realPath.substring(0, realPath.lastIndexOf('/'));

            // obs删除
            obsClient.deleteObject(hweiOBSConfig.getBucketName(), realPath + "/" + key);
        } catch (ObsException e) {
            log.error("obs[deleteFileByPath]删除保存失败", e);
        } finally {
            hweiOBSConfig.destroy(obsClient);
        }
        return false;
    }

    @Override
    public boolean delete(List<String> objectKeys) {
        ObsClient obsClient = null;
        try {
            obsClient = hweiOBSConfig.getInstance();
            DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(hweiOBSConfig.getBucketName());
            objectKeys.forEach(x -> deleteObjectsRequest.addKeyAndVersion(x));
            // 批量删除请求
            obsClient.deleteObjects(deleteObjectsRequest);
            return true;
        } catch (ObsException e) {
            log.error("obs[delete]删除保存失败", e);
        } finally {
            hweiOBSConfig.destroy(obsClient);
        }
        return false;
    }

    @Override
    public String fileUpload(MultipartFile uploadFile, String objectKey) {
        ObsClient obsClient = null;
        try {
            String bucketName = hweiOBSConfig.getBucketName();
            obsClient = hweiOBSConfig.getInstance();
            // 判断桶是否存在
            boolean exists = obsClient.headBucket(bucketName);
            if (!exists) {
                // 若不存在,则创建桶
                HeaderResponse response = obsClient.createBucket(bucketName);
                log.info("创建桶成功" + response.getRequestId());
            }
            InputStream inputStream = uploadFile.getInputStream();
            long available = inputStream.available();
            PutObjectRequest request = new PutObjectRequest(bucketName, objectKey, inputStream);

            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(available);
            request.setMetadata(objectMetadata);
            // 设置对象访问权限为公共读
            request.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ);
            PutObjectResult result = obsClient.putObject(request);

            // 读取该已上传对象的URL
            log.info("已上传对象的URL" + result.getObjectUrl());
            return result.getObjectUrl();
        } catch (ObsException e) {
            log.error("obs[fileUpload]上传失败", e);
        } catch (IOException e) {
            log.error("[fileUpload]上传失败", e);
        } finally {
            hweiOBSConfig.destroy(obsClient);
        }
        return null;
    }

    @Override
    public String uploadFileByte(byte[] data, String fileName) {
        try {
            ObsClient obsClient = null;
            String bucketName = hweiOBSConfig.getBucketName();
            obsClient = hweiOBSConfig.getInstance();
            // 判断桶是否存在
            boolean exists = obsClient.headBucket(bucketName);
            if (!exists) {
                // 若不存在,则创建桶
                HeaderResponse response = obsClient.createBucket(bucketName);
                log.info("创建桶成功" + response.getRequestId());
            }

            String file_http_url = PropertiesUtil.readValue("file_http_url");

            //转为File
            InputStream inputStream = new ByteArrayInputStream(data);
            String prefix = fileName.substring(fileName.lastIndexOf(".") + 1);//后缀
            String uuid = UUID.randomUUID().toString().replace("-", "");//customer_YYYYMMDDHHMM
            fileName = uuid + "." + prefix; //文件全路径
            obsClient.putObject(bucketName, fileName.substring(0, fileName.lastIndexOf("/")) + "/" + fileName, inputStream);
            return file_http_url + fileName;
        } catch (ObsException e) {
            log.error("obs[uploadFileByte]上传失败", e);
        }
        return null;
    }

    @Override
    public String uploadFile(File file) {
        ObsClient obsClient = null;
        try {
            String bucketName = hweiOBSConfig.getBucketName();
            obsClient = hweiOBSConfig.getInstance();
            // 判断桶是否存在
            boolean exists = obsClient.headBucket(bucketName);
            if (!exists) {
                // 若不存在,则创建桶
                HeaderResponse response = obsClient.createBucket(bucketName);
                log.info("创建桶成功" + response.getRequestId());
            }

            String file_http_url = PropertiesUtil.readValue("file_http_url");

            //转为File
            String filename = file.getName();
            String prefix = filename.substring(filename.lastIndexOf(".") + 1);//后缀
            String uuid = UUID.randomUUID().toString().replace("-", "");//customer_YYYYMMDDHHMM
            String fileName = uuid + "." + prefix; //文件全路径
            obsClient.putObject(bucketName, fileName.substring(0, fileName.lastIndexOf("/")) + "/" + fileName, file);
            return file_http_url + fileName;
        } catch (Exception e) {
            log.error("obs[uploadFile]上传失败", e);
        } finally {
            hweiOBSConfig.destroy(obsClient);
        }
        return null;
    }

    @Override
    public InputStream fileDownload(String objectKey) {
        ObsClient obsClient = null;
        try {
            String bucketName = hweiOBSConfig.getBucketName();
            obsClient = hweiOBSConfig.getInstance();
            ObsObject obsObject = obsClient.getObject(bucketName, objectKey);
            return obsObject.getObjectContent();
        } catch (ObsException e) {
            log.error("obs[fileDownload]文件下载失败", e);
        } finally {
            hweiOBSConfig.destroy(obsClient);
        }
        return null;
    }
}

  1. 添加Controller层
package com.elink.license.controller;

import com.elink.license.service.IHweiYunOBSService;
import com.elink.license.util.StringUtils;
import com.elink.share.result.Result;
import com.elink.share.result.ResultCodeWraper;
import com.obs.services.exception.ObsException;
import org.apache.commons.io.IOUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * OBS服务器Controller
 */

@RestController
@RequestMapping({"file"})
public class HweiYunOBSController {

    @Resource
    private IHweiYunOBSService hweiYunOBSService;


    /**
     * upload
     * 上传 file类型文件
     * @param file
     * @return
     */
    @RequestMapping(value = "upload", method = RequestMethod.POST)
    public Map save(@RequestParam(value = "file", required = false) MultipartFile file) {
        if (StringUtils.isEmpty(file)) {
            return new Result<>(ResultCodeWraper.REQUEST_ERROR, "文件为空");
        }
        final String test = hweiYunOBSService.fileUpload(file, file.getOriginalFilename());
        return new Result<>(ResultCodeWraper.SUCCESS, test);
    }


    /**
     * 下载文件
     * /download/123.jpg
     * 注意:此处未将文件名写在路径最后,是因为使用rest方法去下载文件的话,这个方法是会自动截取文件名的后缀,传入的参数将是123,下载后的文件也将丢失后缀
     * {fileName}/download
     *
     * @param request
     * @param response
     * @param fileName
     * @return
     */
    @RequestMapping(value = "{fileName}/download", method = RequestMethod.POST)
    public Map download(HttpServletRequest request, HttpServletResponse response, @PathVariable String fileName) {
        if (StringUtils.isEmpty(fileName)) {
            return new Result<>(ResultCodeWraper.REQUEST_ERROR, "下载文件为空");
        }
        try (
                InputStream inputStream = hweiYunOBSService.fileDownload(fileName);
                BufferedOutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {
            if (inputStream == null) {
                return new Result<>(ResultCodeWraper.REQUEST_ERROR, "内部错误");
            }
            // 为防止 文件名出现乱码
            final String userAgent = request.getHeader("USER-AGENT");
            // IE浏览器
            if (userAgent.indexOf("MSIE") > -1) {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            } else {
                // google,火狐浏览器
                if (userAgent.indexOf("Mozilla") > -1) {
                    fileName = new String(fileName.getBytes(), "ISO8859-1");
                } else {
                    // 其他浏览器
                    fileName = URLEncoder.encode(fileName, "UTF-8");
                }
            }
            response.setContentType("application/x-download");
            // 设置让浏览器弹出下载提示框,而不是直接在浏览器中打开
            response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
            IOUtils.copy(inputStream, outputStream);
            return null;
        } catch (IOException | ObsException e) {
            return new Result<>(ResultCodeWraper.REQUEST_ERROR, "内部错误");
        }
    }


    /**
     * 上传文件---直接传file
     *
     * @return
     */
    public Map uploadFile(File file) {

        if (StringUtils.isEmpty(file)) {
            return new Result<>(ResultCodeWraper.REQUEST_ERROR, "文件为空");
        }
        final String test = hweiYunOBSService.uploadFile(file);
        return new Result<>(ResultCodeWraper.SUCCESS, test);

    }

    /**
     * 上传文件---byte类型
     *
     * @return
     */
    public Map uploadFileByte(byte data[], String fileName) {
        if (StringUtils.isEmpty(fileName)) {
            return new Result<>(ResultCodeWraper.REQUEST_ERROR, "文件为空");
        }
        final String test = hweiYunOBSService.uploadFileByte(data, fileName);
        return new Result<>(ResultCodeWraper.SUCCESS, test);
    }

    /**
     * 下载ObsObject
     * @param filePath   需要下载的文件路径。 例:"site/a.txt"
     * @return  下载文件的字节数组
     * @throws IOException
     */
    public byte[] getFileByteArray(String filePath) throws IOException {
        //filePath : uploadFiles/xiehui/yongjiu/fujian/wode.jpg
        InputStream input = hweiYunOBSService.fileDownload(filePath.substring(0,filePath.lastIndexOf("/")) + "/" + filePath);
        byte[] b = new byte[1024];
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        int len;
        while ((len = input.read(b)) != -1){
            bos.write(b, 0, len);
        }
        bos.close();
        input.close();
        return bos.toByteArray();
    }


    /**
     * 删除文件
     * 根据文件名称删除
     * @param fileName
     * @return
     */
    @RequestMapping(value = "{fileName}/delete", method = RequestMethod.POST)
    public Map delete(@PathVariable String fileName) {
        if (StringUtils.isEmpty(fileName)) {
            return new Result<>(ResultCodeWraper.REQUEST_ERROR, "删除文件为空");
        }
        final boolean delete = hweiYunOBSService.delete(fileName);
        return new Result<>(delete ? ResultCodeWraper.SUCCESS : ResultCodeWraper.REQUEST_ERROR, delete);
    }

    /**
     * 删除文件
     * 根据文件路径删除
     * @param param
     * 待测试 接口
     * https://blog.csdn.net/qq_41992943/article/details/125643664
     */
    @RequestMapping("/deleteFileByPath")
    public Map deleteFileByPath(HttpServletRequest request, @RequestParam Map param) {
        String path = StringUtils.getStringByObj(param.get("path"));
        if (StringUtils.isEmpty(path)) {
            return new Result<>(ResultCodeWraper.REQUEST_ERROR, "文件path为空");
        }
        final boolean delete = hweiYunOBSService.deleteFileByPath(path);
        return new Result<>(delete ? ResultCodeWraper.SUCCESS : ResultCodeWraper.REQUEST_ERROR, delete);
    }

    /**
     * delete
     * 批量删除
     *
     * @param fileNames
     * @return
     */
    @RequestMapping(value = "deletes", method = RequestMethod.POST)
    public Map delete(@RequestParam("fileNames") List<String> fileNames) {
        if (StringUtils.isEmpty(fileNames)) {
            return new Result<>(ResultCodeWraper.REQUEST_ERROR, "删除文件为空");
        }
        final boolean delete = hweiYunOBSService.delete(fileNames);
        return new Result<>(delete ? ResultCodeWraper.SUCCESS : ResultCodeWraper.REQUEST_ERROR, delete);
    }

    /**
     * 递归删除多层目录文件
     * @param path
     */
    public static void dfsdelete(String path) {
        File file = new File(path);
        if (file.isFile()) {//如果此file对象是文件的话,直接删除
            file.delete();
            return;
        }
        //当 file是文件夹的话,先得到文件夹下对应文件的string数组 ,递归调用本身,实现深度优先删除
        String[] list = file.list();
        for (int i = 0; i < list.length; i++) {
            dfsdelete(path + File.separator + list[i]);

        }//当把文件夹内所有文件删完后,此文件夹已然是一个空文件夹,可以使用delete()直接删除
        file.delete();
        return;
    }

    /**
     * 得到文件流
     *
     * @param url 网络图片URL地址
     * @return
     */
    public static byte[] getFileStream(String url) {
        try {
            URL httpUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) httpUrl.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5 * 1000);
            InputStream inStream = conn.getInputStream();//通过输入流获取图片数据
            byte[] btImg = readInputStream(inStream);//得到图片的二进制数据
            return btImg;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 从输入流中获取数据
     *
     * @param inStream 输入流
     * @return
     * @throws Exception
     */
    public static byte[] readInputStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, len);
        }
        inStream.close();
        return outStream.toByteArray();
    }

    /**
     * file转byte
     */
    public static byte[] file2byte(File file) {
        byte[] buffer = null;
        try {
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer;
    }

    /**
     * byte 转file
     */
    public static File byte2File(byte[] buf, String filePath, String fileName) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {
            File dir = new File(filePath);
            if (!dir.exists() && dir.isDirectory()) {
                dir.mkdirs();
            }
            file = new File(filePath + File.separator + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(buf);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return file;
    }

    /**
     * multipartFile转File
     **/
    public static File multipartFile2File(MultipartFile multipartFile) {
        File file = null;
        if (multipartFile != null) {
            try {
                file = File.createTempFile("tmp", null);
                multipartFile.transferTo(file);
                System.gc();
                file.deleteOnExit();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return file;
    }
}

三、测试接口

  1. 上传
    springBoot集成华为云obs对象存储_第1张图片
  2. 下载
    springBoot集成华为云obs对象存储_第2张图片
  3. 删除
    springBoot集成华为云obs对象存储_第3张图片
    注意:上面使用的springBoot版本是1.5.4,使用上述pom依赖没有问题,如果springBoot的版本是2.1.5,则依赖引入如下
<dependency>
   <groupId>com.huaweicloudgroupId>
    <artifactId>esdk-obs-javaartifactId>
    <version>3.21.8version>
dependency>
<dependency>
    <groupId>com.squareup.okhttp3groupId>
    <artifactId>okhttpartifactId>
    <version>4.9.3version>
dependency>
<dependency>
    <groupId>com.squareup.okiogroupId>
    <artifactId>okioartifactId>
    <version>2.8.0version>
dependency>

<dependency>
    <groupId>org.jetbrains.kotlingroupId>
    <artifactId>kotlin-stdlibartifactId>
    <version>1.3.50version>
dependency>

你可能感兴趣的:(java,spring,boot,华为云,java)