Java-整合OSS


前言

最近公司的技术负责人让我整合下 OSS 到项目中,所以花了一点时间研究了下 OSS,虽然说在 OSS 的官方文档中有如何整合 OSS 的详细说明,但是不得不说文档实在是太详细了,如果仅仅是通过看官方文档去整合,可能会看到太多暂时用不上的内容,所以我简化下文档中的内容,也是谨防日后忘记,故此作为分享。

一、OSS 简介

阿里云对象存储 OSS(Object Storage Service)是一款海量、安全、低成本、高可靠的云存储服务,提供最高可达 99.995 % 的服务可用性。多种存储类型供选择,全面优化存储成本。

可以在阿里云的产品列表中找到

地址:https://www.aliyun.com/

在这里插入图片描述

在这里插入图片描述

如果只是想玩一玩,做技术扩展用的,可以买一个商品类型为 OSS 资源包 的,价格很便宜

在这里插入图片描述

对于整合这些第三方的技术,最重要的就是学会去看这些第三方提供的文档

在这里插入图片描述
约莫看一下,大概就知道这些技术是什么?怎么用的

对象存储 OSS 产品文档:https://help.aliyun.com/zh/oss/

在这里插入图片描述

从产品文档中可以看到 OSS 的工作原理:

数据以对象(Object)的形式存储在 OSS 的存储空间(Bucket )中。如果要使用 OSS 存储数据,需要先创建 Bucket,并指定Bucket的地域、访问权限、存储类型等属性。创建 Bucket 后,您可以将数据以 Object 的形式上传到 Bucket,并指定 Object 的文件名(Key)作为其唯一标识。

至少需要了解如下几个概念:

  • 存储空间(Bucket):存储空间是用户用于存储对象(Object)的容器,所有的对象都必须隶属于某个存储空间。存储空间具有各种配置属性,包括地域、访问权限、存储类型等。用户可以根据实际需求,创建不同类型的存储空间来存储不同的数据。
  • 对象(Object):对象是 OSS 存储数据的基本单元,也被称为 OSS 的文件。和传统的文件系统不同,对象没有文件目录层级结构的关系。对象由元信息(Object Meta)、用户数据(Data)和文件名(Key)组成,并且由存储空间内部唯一的 Key 来标识。
  • Region(地域):Region表示OSS的数据中心所在物理位置。用户可以根据费用、请求来源等选择合适的地域创建 Bucket。一般来说,距离用户更近的Region访问速度更快。Region 是在创建 Bucket 的时候指定的。Bucket 创建成功后,Region 将无法修改。
  • Endpoint(访问域名):Endpoint 表示 OSS 对外服务的访问域名。
  • AccessKey(访问密钥):AccessKey 简称 AK,指的是访问身份验证中用到的 AccessKey ID 和 AccessKey Secret。OSS 通过使用 AccessKey ID 和 AccessKey Secret 对称加密的方法来验证某个请求的发送者身份。AccessKey ID 用于标识用户;AccessKey Secret 是用户用于加密签名字符串和 OSS 用来验证签名字符串的密钥,必须保密。

OSS 产品文档 中有详细的说明,我就不多做赘述了。


二、OSS 的使用


1. Bucket 的创建与文件上传

购买 OSS 之后,登录阿里云账号,可在 产品与服务 中找到所购买的 对象存储 OSS

在这里插入图片描述

进入 对象存储 OSS

在这里插入图片描述

点击左侧菜单的 Bucket列表 ,就可以新建 Bucket

在这里插入图片描述

注意:Bucket 新建之后不可修改

在这里插入图片描述

创建成功后可在 Bucket 列表 中看到所创建的 Bucket

在这里插入图片描述

点击该 Bucket 就可以查看其下的 文件列表 与上传文件了

在这里插入图片描述

上传文件完成后会在 文件列表 中展示,可点击详情查看文件下载的 URL

在这里插入图片描述

在这里插入图片描述

可以看到这个 url 的组成:https://bucket.endpoint/filePath


2. 创建 RAM 与用户授权

在网页上虽然可以做这些文件上传等操作,但是需要登录本人的阿里云账号是不安全的,其次是在开发中也不可能在这上面进行操作,都是通过 API 进行文件上传下载等操作。

从上面的 OSS 介绍可知,OSS 的文件是存储在 Bucket 中,如果想要通过程序长期访问 Bucket 下的指定资源,就需要创建 RAM 用户(可以不登录阿里云主账号就能使用指定权限的功能),从而获取 AccessKeyIdAccessKeySecret 作为访问 OSS凭证

关于 RAM 的详细作用可参见 访问控制-RAM用户概览

(1)创建 RAM 用户

  • ① 登录阿里云,找到 AccessKey 管理,点击进入 RAM 控制台,在左侧导航栏,选择 身份管理 > 用户

在这里插入图片描述

  • ② 点击 创建用户 ,输入 登录名称显示名称,访问方式勾选 OpenAPI 调用访问

在这里插入图片描述

进行验证之后

在这里插入图片描述

就能获得 AccessKey IDAccessKey Secret,这个是使用 API 连接 OSS 需要用到的,一定要及时保存 AccessKey 的信息,页面关闭后将无法再次获取信息

(2)RAM 用户分配权限

  • ① 进入 RAM 控制台,在左侧导航栏,选择 身份管理 > 用户,可以看到所有创建好的 RAM 用户
  • ② 在用户页面,单击 目标RAM用户 操作列的 添加权限

在这里插入图片描述

  • ③ 在添加权限面板,为 RAM 用户添加权限

在这里插入图片描述

可以看到 选择权限 这里有很多条,针对控制访问 OSS,只需要勾选 AliyunOSSFullAccess 这个权限,点击保存即可。

在这里插入图片描述

关于 RAM 用户授权 详细说明可参见:为 RAM 用户授权


3. 图形化管理工具-ossbrowser

ossbrowser 是阿里云官方提供的 OSS 图形化管理工具,提供类似 Windows 资源管理器的功能。使用 ossbrowser,您可以快速完成存储空间(Bucket)和文件(Object)的相关操作。

下载:

官方下载地址:https://help.aliyun.com/zh/oss/developer-reference/install-and-log-on-to-ossbrowser

在这里插入图片描述

这里以 windows 64 为例,则下载 Windows 64 下的 oss-browser-win32-x64.zip 压缩包

安装与使用:

下载完成之后,进行解压,在解压后的 oss-browser-win32-x64 文件夹下找到 oss-browser.exe,双击即可打开

在这里插入图片描述

输入之前创建 RAM 用户 时所获取的 AccessKey 账号信息,并且该账户要有访问控制 OSS 的权限(AliyunOSSFullAccess),登入

在这里插入图片描述

在该软件上也可以进行文件上传下载等操作

在这里插入图片描述

我使用这个图形化管理工具的目的主要是为了测试 AccessKey 信息是否能正常连接访问 OSS ~~


三、Java 整合 OSS

关于如何使用 Java 整合 OSS 其实在 OSS 产品文档 中也有比较详细的说明,我们只需要参照 开发参考 中内容基本上都能实现。

在这里插入图片描述

所以我只提供常用的一些常用的功能实现,如果以下内容无法实现你目前的需要,可参考 OSS 产品文档 进行代码编写会比较稳妥。


1. 基本实现

首先是需要安装 OSS 的 Java SDK,在 Maven 工程中只需要在 pom.xml 中加入响应的依赖即可

(1)引入依赖

3.15.1 版本为例,在 <dependencies> 中加入如下内容:

<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.15.1</version>
</dependency>

如果使用的是 Java 9 及以上的版本,则需要添加 jaxb 相关依赖。添加 jaxb 相关依赖示例代码如下:

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>2.3.3</version>
</dependency>

(2)添加配置文件

想要通过程序的方式去连接 OSS,那就必须告诉程序要连接哪个 OSS 端点、哪个 Bucket、并且告诉 OSS 你是谁,交出你的访问凭证

在这里插入图片描述

所以就需要配置 endpointbucketName 以及 AccessKey IdAccessKey Secret 信息,

endpointbucketName 可以在 Bucket 的详情页面获得

在这里插入图片描述

这部分内容一般会放在配置文件中,例如:

yml 文件配置

aliyun:
  oss:
    access-key-id: YOUR_ACCESS_KEY_ID
    access-key-secret: YOUR_ACCESS_KEY_SECRET
    endpoint: oss-cn-xxxxxx.aliyuncs.com
    bucket-name: mike-system-file

配置类 OssProperty.java

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

@Data
@Component
@ConfigurationProperties("aliyun.oss")
public class OssProperty {

    /**
     * AccessKey ID
     */
    private String accessKeyId;

    /**
     * AccessKey Secret
     */
    private String accessKeySecret;

    /**
     * endpoint
     */
    private String endpoint;

    /**
     * bucketName
     */
    private String bucketName;
}

(3)代码编写

OssService.java

import com.aliyun.oss.model.Bucket;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Map;

public interface OssService {

    public static final String HTTPS = "https://";
    public static final String DOT = ".";
    public static final String FORWARD_SLASH = "/";

    /**
     * 列举存储空间
     */
    List<Bucket> showBuckets();

    /**
     * 创建存储空间
     */
    void createBucket(String bucketName);

    /**
     * 删除储存空间
     */
    void removeBucket(String bucketName);

    /**
     * 上传文件
     * @param dir 存储空间某文件夹下,例如:app
     * @param file 上传的文件
     * @return 可访问的路径
     */
    String upload(String dir, MultipartFile file);

    /**
     * 下载文件
     * @param filePath 文件存储全路径,例如:dir/filename(不带 bucket 名称)
     */
    void download(String filePath);

    /**
     * 删除文件
     * @param filePath 文件存储全路径,例如:dir/filename(不带 bucket 名称)
     */
    boolean remove(String filePath);
}

OssServiceImpl.java

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.*;
import com.aliyuncs.exceptions.ClientException;
import com.fsy.common.core.exception.CustomException;
import com.fsy.common.core.utils.DateUtils;
import com.fsy.common.core.utils.ServletUtils;
import com.fsy.tool.config.OssProperty;
import com.fsy.tool.listener.OssProgressListener;
import com.fsy.tool.service.OssService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class OssServiceImpl implements OssService {

    private final OssProperty ossProperty;
    private final HttpServletResponse response;

    /**
     * 获取 OSSClient 实例
     */
    private OSS getOssClient() {
        String endpoint = ossProperty.getEndpoint();
        return new OSSClientBuilder().build(endpoint, ossProperty.getAccessKeyId(), ossProperty.getAccessKeySecret());
    }

	/**
     * 列举存储空间
     */
    @Override
    public List<Bucket> showBuckets() {
        OSS ossClient = getOssClient();
        try {
            // 列举当前账号所有地域下的存储空间
            return ossClient.listBuckets();
        } catch (OSSException e) {
            printlnException(e);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return null;
    }

	/**
     * 创建存储空间
     */
    @Override
    public void createBucket(String bucketName) {
        OSS ossClient = getOssClient();
        try {
            // 创建CreateBucketRequest对象。
            CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);

            // 如果创建存储空间的同时需要指定存储类型、存储空间的读写权限、数据容灾类型, 请参考如下代码
            // 此处以设置存储空间的存储类型为标准存储为例介绍
            //createBucketRequest.setStorageClass(StorageClass.Standard);
            // 数据容灾类型默认为本地冗余存储,即 DataRedundancyType.LRS。如果需要设置数据容灾类型为同城冗余存储,请设置为DataRedundancyType.ZRS
            //createBucketRequest.setDataRedundancyType(DataRedundancyType.ZRS);
            // 设置存储空间读写权限为公共读,默认为私有
            //createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
            // 在支持资源组的地域创建Bucket时,您可以为Bucket配置资源组。
            //createBucketRequest.setResourceGroupId(rsId);

            // 创建存储空间
            ossClient.createBucket(createBucketRequest);
        } catch (OSSException e) {
            printlnException(e);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

	/**
     * 删除储存空间
     */
    @Override
    public void removeBucket(String bucketName) {
        OSS ossClient = getOssClient();
        try {
            // 删除存储空间
            ossClient.deleteBucket(bucketName);
        } catch (OSSException e) {
            printlnException(e);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

	/**
     * 上传文件
     * @param dir 存储空间某文件夹下,例如:app
     * @param file 上传的文件
     * @return 可访问的路径
     */
    @Override
    public String upload(String dir, MultipartFile file) {

        // 获取文件名称
        String sourceName = file.getOriginalFilename();

        // 获取地域节点
        String endpoint = ossProperty.getEndpoint();
        // 获取存储空间名称
        String bucketName = ossProperty.getBucketName();
        // 当前日期
        String ymd = DateUtils.parseDateToStr(DateUtils.YYMMDD, new Date());
        // 文件存放地址(不带 bucket)
        String filePath;
        if (StringUtils.isNotBlank(dir)) {
            // 例如:app/ymd/wms.apk
            filePath = dir + FORWARD_SLASH + ymd + FORWARD_SLASH + sourceName;
        } else {
            filePath = ymd + FORWARD_SLASH + sourceName;
        }

        // 访问路径:https://bucket.endpoint/filePath
        String urlPath = HTTPS + bucketName + DOT +  endpoint + FORWARD_SLASH + filePath;
        // 相对路径
        String relativePath = FORWARD_SLASH + filePath;

        OSS ossClient = getOssClient();

        try {
            // 判断 bucket 是否存在
            if (!ossClient.doesBucketExist(bucketName)) {
                throw new CustomException("存储空间不存在");
            }
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, filePath, file.getInputStream());
            ObjectMetadata metadata = new ObjectMetadata();

            /*
             * 指定存储类型:
             *      对于任意存储类型的Bucket,如果上传Object时指定此参数,则此次上传的Object将存储为指定的类型
             * 取值:
             *      Standard:标准存储
             *      IA:低频访问
             *      Archive:归档存储
             *      ColdArchive:冷归档存储
             *      DeepColdArchive:深度冷归档存储
             */

            // 设置存储类型:标准存储(默认标准存储)
            metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());

            /*
             * 指定上传文件的访问权限:
             * 取值:
             *      default(默认):Object遵循所在存储空间的访问权限
             *      private:私有
             *      public-read:公共读
             *      public-read-write:公共读写
             */

            // 设置访问权限:默认(遵循所在存储空间的访问权限)
            metadata.setObjectAcl(CannedAccessControlList.Default);

            /*
             * 指定上传文件操作时是否覆盖同名 Object:
             *      不指定 x-oss-forbid-overwrite 时,默认覆盖同名 Object
             *      指定 x-oss-forbid-overwrite 为 false 时,表示允许覆盖同名 Object
             *      指定 x-oss-forbid-overwrite 为 true 时,表示禁止覆盖同名 Object,如果同名 Object 已存在,程序将报错
             */

            // 设置禁止覆盖同名文件
            metadata.setHeader("x-oss-forbid-overwrite", "false");

            // 设置元数据
            putObjectRequest.setMetadata(metadata);

            // 上传文件
            ossClient.putObject(putObjectRequest);

        } catch (IOException e) {
            log.error("failed to upload file.detail message:{}", e.getMessage());

        } catch (OSSException e) {
            printlnException(e);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return urlPath;
    }

	/**
     * 下载文件
     * @param filePath 文件存储全路径,例如:dir/filename(不带 bucket 名称)
     */
    @Override
    public void download(String filePath) {

        String bucketName = ossProperty.getBucketName();
        OSS ossClient = getOssClient();

        // 截取文件名称
        String fileName = filePath.substring(filePath.lastIndexOf(FORWARD_SLASH));

        try {
            // 判断文件是否存在
            if (!ossClient.doesObjectExist(bucketName, filePath)) {
                throw new CustomException("文件不存在");
            }

            // ossObject 包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流
            OSSObject ossObject = ossClient.getObject(new GetObjectRequest(bucketName, filePath));
            InputStream inputStream = ossObject.getObjectContent();

            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int num;
            while ((num = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, num);
            }
            byteArrayOutputStream.flush();
            byte[] bytes = byteArrayOutputStream.toByteArray();
            byteArrayOutputStream.close();

            // 读取,返回
            ServletUtils.writeAttachment(response, fileName, bytes);

            // ossObject 对象使用完毕后必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作
            ossObject.close();

        } catch (OSSException oe) {
            printlnException(oe);
        } catch (Throwable ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    @Override
    public boolean remove(String filePath) {
        String bucketName = ossProperty.getBucketName();

        OSS ossClient = getOssClient();
        try {
            // 判断文件是否存在
            if (!ossClient.doesObjectExist(bucketName, filePath)) {
                log.warn("need delete file:{} not exists", filePath);
                return false;
            }
            // 删除文件或目录。如果要删除目录,目录必须为空
            ossClient.deleteObject(bucketName, filePath);

            return true;

        } catch (OSSException oe) {
            printlnException(oe);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return false;
    }

	/**
	 * 返回附件
	 */
	public void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException {
        // 设置 header 和 contentType
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        // 输出附件
        IoUtil.write(response.getOutputStream(), false, content);
    }

    /**
     * 打印异常日志
     */
    public void printlnException(Exception e) {
        if (e instanceof OSSException) {
            OSSException oe = (OSSException) e;
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        }
        if (e instanceof ClientException) {
            ClientException ce = (ClientException) e;
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        }
    }
}

(4)测试

在这里插入图片描述

上传文件

在这里插入图片描述

在这里插入图片描述

以上便是 Java 对 OSS 的简单整合全部内容。

OSS 产品文档 中还有很多个案例,写得也是比较详细,我就不多做赘述了,只要先实现以上的功能,其它的都可以参照产品文档慢慢研究,比如说分片上传、进图条等等。

在这里插入图片描述


2. 客户端直传

除了通过服务器代理上传文件的方式外,OSS 还提供了客户端直传的方式。

在典型的服务端和客户端架构下,常见的文件上传方式是服务端代理上传:客户端将文件上传到业务服务器,然后业务服务器将文件上传到OSS。在这个过程中,一份数据需要在网络上传输两次,会造成网络资源的浪费、增大服务端的资源开销。为了解决这一问题,可以在客户端直连 OSS 来完成文件上传,无需经过业务服务器中转。

在这里插入图片描述

服务端代理上传和客户端直传相比,有以下三个缺点:

  • 上传慢:用户数据先上传到应用服务器,之后再上传到 OSS,网络传输时间比直传到 OSS 多一倍,如果用户数据不通过应用服务器中转,而是直传到 OSS,速度将大大提升,而且 OSS 采用 BGP 宽带,能保证各地各运营商之间的传输速度
  • 扩展性差:如果后续用户多了,应用服务器会成为瓶颈
  • 费用高:需要准备多台应用服务器,用于 OSS 上传流量是免费的,如果数据直传到 OSS,不通过应用服务器,那么将能省下几台应用服务器

从服务端代理上传的案例可知,要想要上传图片,那就必须提供 endpointbucketAccessKey 的信息,但是在前端直接将这些信息写在 js 里面是非常不安全的,容易造成信息泄漏,遭受攻击

所以通常的做法就是前端先向后端发送上传文件的 Post Policy 请求,应用服务器返回签名给前端,前端再携带签名直接将文件上传至 OSS

在这里插入图片描述

后端可以参照 OSS 产品文档 来编写接口,提供签名

在这里插入图片描述

例如(在 基本实现 的案例上添加代码):

Controller

    @GetMapping(value = "/signature")
    @ApiOperation(value = "获取签名")
    public ResponseBean signature(@ApiParam(required = true, value = "上传路径") @RequestParam(required = true) String dir) {
        return ResponseBean.success(ossService.signature(dir));
    }

Service

    /**
     * 服务端签名直传
     * @param dir 设置上传到 OSS 的路径(目录)
     * @return 签名信息
     */
    Map<String, String> signature(String dir);

ServiceImpl

    @Override
    public Map<String, String> signature(String dir) {

        String accessId = ossProperty.getAccessKeyId();
        String endpoint = ossProperty.getEndpoint();
        String bucket = ossProperty.getBucketName();
        // Host 地址,格式为:https://bucket.endpoint
        String host = HTTPS + bucket + DOT +  endpoint;
        // 设置上传回调 URL
        String callbackUrl = "https://www.xxxx.xxx";

        // 创建ossClient实例
        OSS ossClient = getOssClient();
        try {
            long expireTime = 30;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConditions = new PolicyConditions();
            policyConditions.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConditions.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConditions);
            byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            Map<String, String> respMap = new LinkedHashMap<>();
            respMap.put("access_id", accessId);
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));

            /*
             * 设置回调接口的一些相关参数
             * 
             *      JSONObject jasonCallback = new JSONObject();
             *      jasonCallback.put("callbackUrl", callbackUrl);
             *      jasonCallback.put("callbackBody",
             *              "filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
             *      jasonCallback.put("callbackBodyType", "application/x-www-form-urlencoded");
             *      String base64CallbackBody = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());
             *      respMap.put("callback", base64CallbackBody);
             */
            
            return respMap;

        } catch (Exception e) {
            // Assert.fail(e.getMessage());
            System.out.println(e.getMessage());
        }
        return null;
    }

Body中的各字段说明如下:

字段描述
accessid用户请求的AccessKey ID
host用户发送上传请求的域名
policy用户表单上传的策略(Policy),Policy为经过Base64编码过的字符串。详情请参见Post Policy
signature对Policy签名后的字符串
expire由服务器端指定的Policy过期时间,格式为Unix时间戳(自UTC时间1970年01月01号开始的秒数)
dir限制上传的文件前缀

测试:

在这里插入图片描述

后端就这样写就行了,

前端 vue + element-ui,OSS 上传文件代码如下:

...

未完待续...


参考博客

JAVA整合阿里云OSS/VUE上传阿里云OSS:https://blog.51cto.com/u_15899048/5903392

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot可以很方便地集成阿里云的对象存储服务(OSS)。下面是整合步骤: 1. 首先,在你的Spring Boot项目中添加阿里云OSS的依赖,可以在pom.xml文件中加入以下代码: ```xml <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>3.13.1</version> </dependency> ``` 2. 创建一个配置类,用于配置阿里云OSS的相关参数,比如accessKeyId、accessKeySecret等。可以在src/main/java目录下创建一个`OSSConfig.java`文件,并添加如下代码: ```java import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class OSSConfig { @Value("${oss.endpoint}") private String endpoint; @Value("${oss.accessKeyId}") private String accessKeyId; @Value("${oss.accessKeySecret}") private String accessKeySecret; @Bean public OSS ossClient() { return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); } } ``` 3. 在application.properties或application.yml文件中添加配置,例如: application.properties: ```properties oss.endpoint=your_endpoint oss.accessKeyId=your_access_key_id oss.accessKeySecret=your_access_key_secret ``` application.yml: ```yaml oss: endpoint: your_endpoint accessKeyId: your_access_key_id accessKeySecret: your_access_key_secret ``` 4. 在你的代码中使用已经注入的OSS bean来操作对象存储服务。例如,上传文件: ```java import com.aliyun.oss.OSS; import com.aliyun.oss.model.PutObjectRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class OSSService { @Autowired private OSS ossClient; public void uploadFile(String bucketName, String objectName, String filePath) { ossClient.putObject(new PutObjectRequest(bucketName, objectName, new File(filePath))); } } ``` 这样就完成了Spring Boot与阿里云OSS整合,你可以根据自己的需求进行更多操作,比如下载文件、删除文件等。希望对你有帮助!如果还有其他问题,请继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值