谷粒商城--品牌管理(OSS、JSR303数据校验)-1

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,内容安全 1000次 1年
对象存储 OSS,恶意文件检测 1000次 1年
简介: 谷粒商城--品牌管理(OSS、JSR303数据校验)

前言


Github地址:https://github.com/YuyanCai/mall-study


简单上传测试


OSS是对象存储服务,有什么用呢?把图片存储到云服务器上能让所有人都访问到!


详细操作可查官方文档,下面只写关键代码


[SDK示例 (aliyun.com)](https://help.aliyun.com/document_detail/32008.html)


一、创建子用户测试用例


官方推荐使用子账户的AccessID和SecurityID,因为如果直接给账户的AccessID和SecurityID的话,如果不小心被其他人获取到了,那账户可是有全部权限的!!!


所以这里通过建立子账户,给子账户分配部分权限实习。


这里通过子账户管理OSS的时候,要给子账户添加操控OSS资源的权限

这里是必须要做的,因为子账户默认是没有任何权限的,必须手动给他赋予权限


cea9e0f61d4749292464dd766e6141c4_fd9753ca20dbe9bf01844590b7d3f601.png


二、引入依赖


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

三、测试用例


@SpringBootTest
class MallProductApplicationTests {
    @Test
    public void testUploads() throws FileNotFoundException {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = "。。。";
        String accessKeySecret = "。。。";
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "pyy-mall";
        // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
        String objectName = "2022/testPhoto.txt";
        // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
        // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
        String filePath= "C:\\Users\\Jack\\Desktop\\R-C.jfif";
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            InputStream inputStream = new FileInputStream(filePath);
            // 创建PutObject请求。
            ossClient.putObject(bucketName, objectName, inputStream);
        } 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();
            }
        }
    }
}

f8ff6f3ff487a637acb974593725fbe4_2e56a0b80f5aaba51586d45d4ba149f4.png


Aliyun Spring Boot OSS


https://github.com/alibaba/aliyun-spring-boot/blob/master/aliyun-spring-boot-samples/aliyun-oss-spring-boot-sample/README-zh.md


一、引入依赖


我们不是进行依赖管理了吗?为什么还要显示写出2.1.1版本


这是因为这个包没有最新的包,只有和2.1.1匹配的


        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alicloud-oss</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>

二、在配置文件中配置 OSS 服务对应的 accessKey、secretKey 和 endpoint

    alicloud:
      access-key: xxx
      secret-key: xxx
      oss:
        endpoint: oss-cn-hangzhou.aliyuncs.com

三、注入OSSClient测试


@Resource
private OSSClient ossClient;
@Test
public void testUploads() throws FileNotFoundException {
    // 上传文件流。
    InputStream inputStream = new FileInputStream("C:\\Users\\Jack\\Desktop\\LeetCode_Sharing.png");
    ossClient.putObject("pyy-mall", "2022/testPhoto2.png", inputStream);
    // 关闭OSSClient。
    ossClient.shutdown();
    System.out.println("上传完成...");
}

f8c0127c558bf8295a360d8ab7d27cce_cfce9142a427d41667aa491fb73c8c95.png


新模块mall-third-service


新模块存放所有的第三方服务,像短信服务、图片服务、视频服务等等


引入依赖如下:


这里去除了mp的依赖,因为引入mp就需要配置数据库服务器地址


接口开发

一、配置文件


<dependencies>
    <dependency>
        <groupId>com.caq.mall</groupId>
        <artifactId>mall-common</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <exclusions>
            <exclusion>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alicloud-oss</artifactId>
        <version>2.1.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

ab7b3cd9d68bd610af4846099f914450_ea31ab8cec57ad71b358e88622da7758.png


二、启动类添加注解


将第三方的包也注册到注册中心


  • 主启动类@EnableDiscoveryClient


  • application.yml配置文件如下:


#用来指定注册中心地址
spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #nacos地址
    alicloud:
      access-key: ...
      secret-key: ...
      oss:
        endpoint: oss-cn-hangzhou.aliyuncs.com
        bucket: pyy-mall
  • bootstrap.yml文件指定注册中心


#用来指定配置中心地址
spring:
  application:
    name: mall-third-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        namespace: 2bbd2076-36c8-44b2-9c2e-17ce5406afb7
        file-extension: yaml
        extension-configs:
          - data-id: mall-third-service.yml
            group: DEFAULT_GROUP
            refresh: true

三、测试


@SpringBootTest
class MallThirdServiceApplicationTests {
    @Resource
    OSSClient ossClient;
    @Test
    void contextLoads() throws FileNotFoundException {
        // 上传文件流。
        InputStream inputStream = new FileInputStream("C:\\Users\\Jack\\Desktop\\LeetCode_Sharing.png");
        ossClient.putObject("pyy-mall", "2022/testPhoto3.png", inputStream);
        // 关闭OSSClient。
        ossClient.shutdown();
        System.out.println("上传完成...");
    }
}

没问题!


四、改善上传


服务端签名后直传


采用JavaScript客户端直接签名(参见JavaScript客户端签名直传)时,AccessKeyID和AcessKeySecret会暴露在前端页面,因此存在严重的安全隐患。


因此,OSS提供了服务端签名后直传的方案。


  • 向服务器获取到签名,再去请求oss服务器

controller如下:


这里定义返回类为R是为了统一返回结果,到后面也会用到


package com.caq.mall.thirdservice.controller;
@RestController
@RequestMapping("oss")
public class OssController {
    @Resource
    private OSS ossClient;
    @Value("${spring.cloud.alicloud.oss.endpoint}")
    public String endpoint;
    @Value("${spring.cloud.alicloud.oss.bucket}")
    public String bucket;
    @Value("${spring.cloud.alicloud.access-key}")
    public String accessId;
    private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
    @GetMapping("/policy")
    public R getPolicy(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
        // callbackUrl为上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
        //        String callbackUrl = "http://88.88.88.88:8888";
        String dir = format.format(new Date())+"/"; // 用户上传文件时指定的前缀。以日期格式存储
        // 创建OSSClient实例。
        Map<String, String> respMap= null;
        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 = new LinkedHashMap<String, String>();
            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));
        } catch (Exception e) {
            // Assert.fail(e.getMessage());
            System.out.println(e.getMessage());
        } finally {
            ossClient.shutdown();
        }
        return R.ok().put("data",respMap);
    }
}

测试这个请求,http://localhost:9988/oss/policy,成功获取


fcaee1234e49ae872fc67d5cc6b0c159_bdbfc083dd78a9a5b3950cf6a7ffa0b1.png


五、设置网关代理

- id: mall-third-service
  uri: lb://mall-third-service
  predicates:
    - Path=/api/thirdservice/**
  filters:
    - RewritePath= /api/thirdservice/(?<segment>.*),/$\{segment}

测试这个请求,http://localhost:88/api/thirdservice/oss/policy


a8eb8117466d16cb3a77822866822bd9_8c58718e08aa65b8ae612967d1b03034.png


至此,我们的功能都没问题了,那么现在就来前端的代码


singleUpload.vue

单文件上传组件


<template>
  <div>
    <el-upload
      action="http://gulimall-hello.oss-cn-beijing.aliyuncs.com"
      :data="dataObj"
      list-type="picture"
      :multiple="false" :show-file-list="showFileList"
      :file-list="fileList"
      :before-upload="beforeUpload"
      :on-remove="handleRemove"
      :on-success="handleUploadSuccess"
      :on-preview="handlePreview">
      <el-button size="small" type="primary">点击上传</el-button>
      <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过10MB</div>
    </el-upload>
    <el-dialog :visible.sync="dialogVisible">
      <img width="100%" :src="fileList[0].url" alt="">
    </el-dialog>
  </div>
</template>
<script>
   import {policy} from './policy'
   import { getUUID } from '@/utils'
  export default {
    name: 'singleUpload',
    props: {
      value: String
    },
    computed: {
      imageUrl() {
        return this.value;
      },
      imageName() {
        if (this.value != null && this.value !== '') {
          return this.value.substr(this.value.lastIndexOf("/") + 1);
        } else {
          return null;
        }
      },
      fileList() {
        return [{
          name: this.imageName,
          url: this.imageUrl
        }]
      },
      showFileList: {
        get: function () {
          return this.value !== null && this.value !== ''&& this.value!==undefined;
        },
        set: function (newValue) {
        }
      }
    },
    data() {
      return {
        dataObj: {
          policy: '',
          signature: '',
          key: '',
          ossaccessKeyId: '',
          dir: '',
          host: '',
          // callback:'',
        },
        dialogVisible: false
      };
    },
    methods: {
      emitInput(val) {
        this.$emit('input', val)
      },
      handleRemove(file, fileList) {
        this.emitInput('');
      },
      handlePreview(file) {
        this.dialogVisible = true;
      },
      beforeUpload(file) {
        let _self = this;
        return new Promise((resolve, reject) => {
          policy().then(response => {
            console.log("响应的数据",response);
            _self.dataObj.policy = response.data.policy;
            _self.dataObj.signature = response.data.signature;
            _self.dataObj.ossaccessKeyId = response.data.accessid;
            _self.dataObj.key = response.data.dir +getUUID()+'_${filename}';
            _self.dataObj.dir = response.data.dir;
            _self.dataObj.host = response.data.host;
            console.log("响应的数据222。。。",_self.dataObj);
            resolve(true)
          }).catch(err => {
            reject(false)
          })
        })
      },
      handleUploadSuccess(res, file) {
        console.log("上传成功...")
        this.showFileList = true;
        this.fileList.pop();
        this.fileList.push({name: file.name, url: this.dataObj.host + '/' + this.dataObj.key.replace("${filename}",file.name) });
        this.emitInput(this.fileList[0].url);
      }
    }
  }
</script>
<style>
</style>
相关实践学习
借助OSS搭建在线教育视频课程分享网站
本教程介绍如何基于云服务器ECS和对象存储OSS,搭建一个在线教育视频课程分享网站。
相关文章
|
存储 弹性计算 安全
对象存储OSS快速上手——ossutil工具管理OSS
本实验是对象存储OSS进阶实验。通过本实验,用户可学会如何使用ossutil工具在Linux环境下用命令管理oss,完成文件上传下载等操作。
|
6月前
|
存储 安全 前端开发
APP管理后台OSS技术改造
旨在记录之前使用的上传文件是放在服务器的现在改成了oss更加高效管理
|
7月前
|
存储 编解码 监控
使用oss服务管理对象
使用oss服务管理对象
72 1
|
对象存储
谷粒商城--品牌管理(OSS、JSR303数据校验)-3
谷粒商城--品牌管理(OSS、JSR303数据校验)
70 0
|
前端开发 Java API
谷粒商城--品牌管理(OSS、JSR303数据校验)-2
谷粒商城--品牌管理(OSS、JSR303数据校验)
89 0
|
数据可视化 数据挖掘 数据库
TDengine OSS 与 qStudio 实现无缝协同,革新数据分析和管理方式
为了帮助社区用户更好地进行数据分析和管理,丰富可视化解决方案的多样性,我们将开源的时序数据库 TDengine OSS 与开源的数据库分析工具进行了集成,相信这对终极开源工具一定能帮助你释放数据潜力。
130 0
java202304java学习笔记第五十二天员工管理-阿里云oss-集成服务2
java202304java学习笔记第五十二天员工管理-阿里云oss-集成服务2
91 0
|
5月前
|
机器学习/深度学习 人工智能 专有云
人工智能平台PAI使用问题之怎么将DLC的数据写入到另一个阿里云主账号的OSS中
阿里云人工智能平台PAI是一个功能强大、易于使用的AI开发平台,旨在降低AI开发门槛,加速创新,助力企业和开发者高效构建、部署和管理人工智能应用。其中包含了一系列相互协同的产品与服务,共同构成一个完整的人工智能开发与应用生态系统。以下是对PAI产品使用合集的概述,涵盖数据处理、模型开发、训练加速、模型部署及管理等多个环节。
|
1月前
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
4月前
|
存储 机器学习/深度学习 弹性计算
阿里云EMR数据湖文件系统问题之OSS-HDFS全托管服务的问题如何解决
阿里云EMR数据湖文件系统问题之OSS-HDFS全托管服务的问题如何解决