资讯详情

java 使用 阿里云OSS云存储

文章目录

  • 开启云存储的阿里云
  • 使用
    • 术语
    • 创建
    • 快速测试上传文件
    • java上传
      • 1 创建子用户
      • 2.1 方法1:(推荐方法2)
        • 步骤
        • 代码
          • pom
          • 上传文件
      • 2.2 方法2:
        • pom 引入依赖
        • yaml
        • 上传上传代码
    • 服务端签名后直接传输
      • 签名的主要内容
      • yaml主要内容:
      • 编写controller,返回签名信息
      • 前端
        • 上传文件的组件:
          • 单文件:
          • 多文件:
          • 从后端获取签名
          • ==跨域问题==
分布式文件存储,浏览器上传的文件,统一存储到服务器中

本文选择统一存储到云存储

开启云存储的阿里云

  • 先贴计费,很便宜 原文:https://www.aliyun.com/price/product?spm=5176.8465980.help.3.4e701450R42spo#/oss/detail/ossbag 在这里插入图片描述

  • aliyun官网 - 产品 - oss对象存储

  • 开通

  • 如果没有实名认证,需要认证,支付宝认证,大约一分钟

使用

术语

  • 存储空间 Bucket 存储空间是您用来存储对象的(Object)容器,所有对象都必须属于某个存储空间。
  • 对象/文件 Object 对象是 OSS 存储数据的基本单元,被称为OSS文件。对象由元信息(Object Meta)、用户数据(Data)和文件名(Key)组成对象由存储空间内唯一的对象组成Key来标识。
  • 地域 Region 地域表示 OSS 数据中心的物理位置。您可以根据成本、请求来源等综合选择数据存储区域。详情请查看OSS已经开通的Region。
  • 访问域名 Endpoint Endpoint 表示OSS访问域名的外部服务。OSS以HTTP RESTful API以外部服务的形式,当访问不同的区域时,需要不同的域名。通过内部网络和外部网络访问同一区域所需的域名也有所不同。具体内容请参见每个区域Region对应的Endpoint。
  • 访问密钥 AccessKey AccessKey,简称 AK,指访问身份验证中使用的AccessKeyId 和AccessKeySecret。OSS通过使用AccessKeyId 和AccessKeySecret通过对称加密来验证请求的发送者身份。AccessKeyId识别用户,AccessKeySecret加密签名字符串和OSS用于验证签名字符串的密钥AccessKeySecret 必须保密。

创建

  • 右侧点创建
  • 选项(根据实际需要选择)

快速测试上传文件

  • 选择上传文件
  • 查看图片 访问如下位置网址:

java上传

java上传文件需要上传到后台,然后上传到后台oss对象存储,自己的服务器也存储了一遍文件,不划算。

服务端签名后上传(本文背后)是指从后台获得签名后直接从前端上传,效率更高。

1 创建子用户

  • 通过自己的用户名密码直接验证是不安全的。创建子用户并授权其
  • 网址 https://ram.consol.aliyun.com/users
  • 如图所示的两个内容相当于用户名密码,要复制下来,一会要用,一会再进来是看不到AccessKey Secret内容的!
  • 授权
    1. 先返回
    2. 添加权限
    3. 添加如下权限
    4. 成功

2.1 方法1:(推荐方法2)

步骤

代码

pom
  • 在Maven项目中加入依赖项 在Maven工程中使用OSS Java SDK,只需在pom.xml中加入相应依赖即可。以3.10.2版本为例,在中加入如下内容:
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.10.2</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>
上传文件
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import java.io.File;

public class Demo { 
        

    public static void main(String[] args) throws Exception { 
        
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = "yourAccessKeyId";
        String accessKeySecret = "yourAccessKeySecret";
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
        String objectName = "exampledir/exampleobject.txt";
        // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
        // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
        String filePath= "D:\\localpath\\examplefile.txt";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try { 
        
            // 创建PutObjectRequest对象。 
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new File(filePath));
            // 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。
            // ObjectMetadata metadata = new ObjectMetadata();
            // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
            // metadata.setObjectAcl(CannedAccessControlList.Private);
            // putObjectRequest.setMetadata(metadata);

            // 上传文件。
            ossClient.putObject(putObjectRequest);
        } catch (OSSException oe) { 
        
            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());
        } catch (ClientException 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();
            }
        }
    }
}            

2.2 方法2:

Alibaba Cloud OSS: 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。 原文:https://github.com/alibaba/aliyun-spring-boot/tree/master/aliyun-spring-boot-samples/aliyun-oss-spring-boot-sample

pom 引入依赖

<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alicloud-oss -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
    <version>2.2.0.RELEASE</version>
</dependency>
  • 附上官方文档的依赖,导入失败
<dependency>
   <groupId>com.alibaba.cloud</groupId>
   <artifactId>aliyun-oss-spring-boot-starter</artifactId>
</dependency>

yaml

  • 配置accessKeyId, secretAccessKey 和region,获取方法原文有
spring:
  cloud:
    alicloud:
      access-key: xx
      secret-key: xx
      oss:
        endpoint: xx

文件上传代码

  • 文件上传
    @Resource
    private OSSClient ossClient;

    @Test
    public void saveFile() { 
        
        // 上传
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
        String objectName = "exampledir/exampleobject.txt";
        ossClient.putObject(new PutObjectRequest(bucketName, objectName, new File("C:\\Users\\AikeTech\\Pictures\\Saved Pictures\\20220223214433.jpg")));
        System.out.println("上传成功。。。");
    }

服务端签名后直传

原文:https://help.aliyun.com/document_detail/31926.html

签名主要内容

{ 
        
"accessid":"LTAI5tBDFVar1hoq****",
"host":"http://post-test.oss-cn-hangzhou.aliyuncs.com",
"policy":"eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8i****",
"signature":"VsxOcOudx******z93CLaXPz+4s=",
"expire":1446727949,
"dir":"user-dirs/"
}

Body中的各字段说明如下:

accessid 用户请求的AccessKey ID。

host 用户发送上传请求的域名。

policy用户表单上传的策略(Policy),Policy为经过Base64编码过的字符串。详情请参见Post Policy。

signature 对Policy签名后的字符串。详情请参见Post Signature。

expire由服务器端指定的Policy过期时间,格式为Unix时间戳(自UTC时间1970年01月01号开始的秒数)。

dir限制上传的文件前缀。

yaml主要内容:

spring: 
    cloud:
      alicloud:
        access-key: xx
        secret-key: xx
        oss:
          endpoint: xx
          # 自定义属性bucket
          bucket: xx
server: 
  port: 30000

编写controller,返回签名信息

@RestController
@Slf4j
public class OssController { 
        
    @Resource
    OSS ossClient;

    // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
    @Value("${spring.cloud.alicloud.access-key}")
    String accessId ;

    @Value("${spring.cloud.alicloud.secret-key}")
    String accessKey ;

    // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
    @Value("${spring.cloud.alicloud.oss.endpoint}")
    String endpoint ;

    // 填写Bucket名称,例如examplebucket。
    @Value("${spring.cloud.alicloud.oss.bucket}")
    String bucket ;
    // 设置上传回调URL,即回调服务器地址,用于处理应用服务器与OSS之间的通信。OSS会在文件上传完成后,把文件上传信息通过此回调URL发送给应用服务器。
    //String callbackUrl = "https://192.168.0.0:8888";

    @RequestMapping("/oss/policy")
    protected R generatePostPolicy() { 
        

        // 填写Host名称,格式为https://bucketname.endpoint。
        String host = "https://" + bucket + "." + endpoint;

        // 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String dir = format.format(new Date())  + "/";//注意,有/

        Map<String, String> respMap = new LinkedHashMap<String, String>();
        try { 
        
            long expireTime = 30;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            // PostObject请求最大可支持的文件大小为5 GB,即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            respMap.put("accessid", accessId);
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));
            // respMap.put("expire", formatISO8601Date(expiration));

// 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);
        } catch (Exception e) { 
        
            // Assert.fail(e.getMessage());
            log.info(e.getMessage());
        } finally { 
        
            ossClient.shutdown();
        }
        return R.ok().put("data", respMap);
    }
}

锐单商城 - 一站式电子元器件采购平台