• 商城项目09_品牌管理菜单、快速显示开关、阿里云进行文件上传、结合Alibaba管理OSS、服务端签名后直传


    ①. 品牌管理菜单

    • ①. 后台:系统管理/菜单管理/新增
      在这里插入图片描述

    • ②. 将逆向工程product得到的resources\src\views\modules\product文件拷贝到gulimall/renren-fast-vue/src/views/modules/product目录下’也就是下面的两个文件
      brand.vue : 显示的表单
      brand-add-or-update.vue:添加和更改功能

    • ③. 但是显示的页面没有新增和删除功能’这是因为权限控制的原因
      在这里插入图片描述

    <el-button v-if="isAuth('product:brand:save')" type="primary" @click="addOrUpdateHandle()">新增</el-button>
    <el-button v-if="isAuth('product:brand:delete')" type="danger" @click="deleteHandle()" :disabled="dataListSelections.length <= 0">批量删除</el-button>
    
    • 1
    • 2
    • ④. 查看“isAuth”的定义位置:将方法的返回值返回true,然后再次刷新页面(也可以将v-if注释掉)
      在这里插入图片描述
      在这里插入图片描述
    • ⑤. 注释掉检测语法
      build/webpack.base.conf.js 中注释掉createLintingRule()函数体’不进行lint语法检查
      在这里插入图片描述

    ②. 快速显示开关

    • ①. 实现的效果如下
      在这里插入图片描述
    • ②. 前台页面(参照elementui进行显示)
    <el-table-column
       prop="showStatus"
       header-align="center"
       align="center"
       label="显示状态"
       width="200"
     >
       <template slot-scope="scope">
         <el-switch
           v-model="scope.row.showStatus"
           active-color="#13ce66"
           inactive-color="#ff4949"
           :active-value="1"
           :inactive-value="0"
           @change="updateBrandStatus(scope.row)"
         >el-switch>
       template>
    el-table-column>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    //更新开关的状态
    updateBrandStatus(data) {
      // 传入了改变行的数据
      console.log("最新状态", data);
      let { brandId, showStatus } = data;
      this.$http({
        url: this.$http.adornUrl("/product/brand/update"),
        method: "post",
        data: this.$http.adornData({ brandId, showStatus }, false)
      }).then(({ data }) => {
        this.$message({
          message: "状态更新成功",
          type: "success"
        });
      });
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • ③. 后台接口
    @RestController
    @RequestMapping("product/brand")
    public class BrandController {
        /** * 修改 */
        @RequestMapping("/update")
        public R update(@RequestBody BrandEntity brand){
            brandService.updateById(brand);
            return R.ok();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    @Data
    @TableName("pms_brand")
    public class BrandEntity implements Serializable {
    	private static final long serialVersionUID = 1L;
    	/* 品牌id */
    	@TableId
    	private Long brandId;
    	/*** 品牌名 */
    	private String name;
    	/*** 品牌logo地址 */
    	private String logo;
    	/*** 介绍 */
    	private String descript;
    	/**
    	 * 显示状态[0-不显示;1-显示]
    	 */
    	private Integer showStatus;
    	/** * 检索首字母 */
    	private String firstLetter;
    	/** * 排序 */
    	private Integer sort;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • ④. 在新增或者修改的时候也要将按钮进行修改
      brand-add-or-update.vue
    <el-form-item label="显示状态" prop="showStatus">
        <el-switch v-model="dataForm.showStatus"
                   active-color="#13ce66"
                   inactive-color="#ff4949"
                   :active-value="1"
                   :inactive-value="0"
                   >
        el-switch>
    el-form-item>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    ③. 阿里云上传概述

    • ①. 阿里云上使使用对象存储方式:
      在这里插入图片描述

    • ②. 创建Bucket,我们的Bucket名称叫 gulimall-tangzhi
      在这里插入图片描述

    • ③. 上传文件:上传成功后’取得图片的URL
      这种方式是手动上传图片’实际上我们可以在程序中设置自动上传图片到阿里云对象存在这里插入图片描述

    • ④. 我们后续将采用下面的方式进行图片的储存
      在这里插入图片描述

    ④. 使用代码进行文件上传

    <dependency>
        <groupId>com.aliyun.ossgroupId>
        <artifactId>aliyun-sdk-ossartifactId>
        <version>3.8.0version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    // Endpoint以杭州为例'其它Region请按实际情况填写。
    String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
    // 云账号AccessKey有所有API访问权限'建议遵循阿里云安全最佳实践'创建并使用RAM子账号进行API访问或日常运维'请登录 https://ram.console.aliyun.com 创建。
    String accessKeyId = "";
    String accessKeySecret = "";
    
    // 创建OSSClient实例。
    OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    
    // 上传文件流。
    InputStream inputStream = new FileInputStream("");
    ossClient.putObject("", "", inputStream);
    
    // 关闭OSSClient。
    ossClient.shutdown();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
     @Test
        public void upload()throws Exception{
            // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例'Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
            String endpoint = "oss-cn-guangzhou.aliyuncs.com";
            // 阿里云账号AccessKey拥有所有API的访问权限'风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维'请登录RAM控制台创建RAM用户。
            String accessKeyId = "LTAI5t7E9sokgukBNzP45nX1";
            String accessKeySecret = "yKzdbTeQETI4u9okOAPDvSscEa5pVT";
    
            // 创建OSSClient实例。
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    
            // 填写本地文件的完整路径。如果未指定本地路径'则默认从示例程序所属项目对应本地路径中上传文件流。
            InputStream inputStream = new FileInputStream("C:\\Users\\Administrator\\Desktop\\car.jpg");
            // 依次填写Bucket名称(例如examplebucket)和Object完整路径(例如exampledir/exampleobject.txt)。Object完整路径中不能包含Bucket名称。
            ossClient.putObject("gulimall-tangzhi", "car.jpg", inputStream);
    
            // 关闭OSSClient。
            ossClient.shutdown();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    • ③. endpoint指的是什么?
      在这里插入图片描述
    • ④. accessKeyId和accessKeySecret指的是什么?

    步骤
    (1). accessKeyId和accessKeySecret需要创建一个RAM账号:
    在这里插入图片描述在这里插入图片描述在这里插入图片描述
    (2). 创建用户完毕后’会得到一个“AccessKey ID”和“AccessKeySecret”'然后复制这两个值到代码的“AccessKey ID”和“AccessKeySecret”。另外还需要添加访问控制权限:
    在这里插入图片描述

    • ⑤. 我们在项目中使用的是SpringCloud Alibaba来管理oss,后续会进行介绍

    ⑤. 结合Alibaba来管理oss

    1. Add dependency aliyun-oss-spring-boot-starter in the pom.xml file in your Spring Boot project.
    2. Configure accessKeyId, secretAccessKey and region in application.properties.
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>aliyun-oss-spring-boot-starterartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    // application.properties
    alibaba.cloud.access-key=your-ak
    alibaba.cloud.secret-key=your-sk
    alibaba.cloud.oss.endpoint=***
    
    • 1
    • 2
    • 3
    • 4
    • ③. 我们在common工程中引入oss的依赖

    • ④. 在product工程中进行测试

    # DataSource Config
    spring:
      cloud:
        alicloud:
          access-key: LTAI5t7E9sokgukBNzP45nX1
          secret-key: yKzdbTeQETI4u9okOAPDvSscEa5pVT
          oss:
            endpoint: oss-cn-guangzhou.aliyuncs.com
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    @Resource
    OSSClient ossClient;
    
    @Test
    public void uploadCloudAlibaba()throws Exception{
        // 填写本地文件的完整路径。如果未指定本地路径'则默认从示例程序所属项目对应本地路径中上传文件流。
        InputStream inputStream = new FileInputStream("C:\\Users\\Administrator\\Desktop\\car2.jpg");
        // 依次填写Bucket名称(例如examplebucket)和Object完整路径(例如exampledir/exampleobject.txt)。Object完整路径中不能包含Bucket名称。
        ossClient.putObject("gulimall-tangzhi", "car2.jpg", inputStream);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    • ⑤. 但是这样来做还是比较麻烦’如果以后的上传任务都交给gulimall-product来完成’显然耦合度高。最好单独新建一个Module来完成文件上传任务

    ⑥. gulimall-third-party微服务

    • ①. 环境配置如下
      因为在common工程中引入了mybatis-plus,我们这个gulimall-third-party服务将其依赖进行排除掉

    在这里插入图片描述

    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0modelVersion>
        <parent>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-parentartifactId>
            <version>2.1.8.RELEASEversion>
            <relativePath/> 
        parent>
        <groupId>com.atguigu.gulimallgroupId>
        <artifactId>gulimall-third-partyartifactId>
        <version>0.0.1-SNAPSHOTversion>
        <name>gulimall-third-partyname>
        <description>第三方服务description>
    
        <properties>
            <java.version>1.8java.version>
            <spring-cloud.version>Greenwich.SR3spring-cloud.version>
        properties>
    
    
        <dependencies>
            <dependency>
                <groupId>com.atguigu.gulimallgroupId>
                <artifactId>gulimall-commonartifactId>
                <version>0.0.1-SNAPSHOTversion>
                <exclusions>
                    <exclusion>
                        <groupId>com.baomidougroupId>
                        <artifactId>mybatis-plus-boot-starterartifactId>
                    exclusion>
                exclusions>
            dependency>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-starter-openfeignartifactId>
            dependency>
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-starter-alicloud-ossartifactId>
            dependency>
    
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
                <scope>testscope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintagegroupId>
                        <artifactId>junit-vintage-engineartifactId>
                    exclusion>
                exclusions>
            dependency>
        dependencies>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloudgroupId>
                    <artifactId>spring-cloud-dependenciesartifactId>
                    <version>${spring-cloud.version}version>
                    <type>pomtype>
                    <scope>importscope>
                dependency>
                <dependency>
                    <groupId>com.alibaba.cloudgroupId>
                    <artifactId>spring-cloud-alibaba-dependenciesartifactId>
                    <version>2.1.0.RELEASEversion>
                    <type>pomtype>
                    <scope>importscope>
                dependency>
            dependencies>
        dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-maven-pluginartifactId>
                plugin>
            plugins>
        build>
    
        <repositories>
            <repository>
                <id>spring-milestonesid>
                <name>Spring Milestonesname>
                <url>https://repo.spring.io/milestoneurl>
            repository>
        repositories>
    project>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • ②. bootstrap.properties配置nacos配置中心
      在这里插入图片描述
    spring.application.name=gulimall-third-party
    spring.cloud.nacos.config.server-addr=127.0.0.1:8848
    spring.cloud.nacos.config.namespace=39e31ec7-194c-4741-b4f2-2b65142c2100
    spring.cloud.nacos.config.ext-config[0].data-id=oss.yml
    spring.cloud.nacos.config.ext-config[0].group=DEFAULT_GROUP
    spring.cloud.nacos.config.ext-config[0].refresh=true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • ③. application.yaml
    spring:
      cloud:
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848
        alicloud:
          access-key: LTAI5t7E9sokgukBNzP45nX1
          secret-key: yKzdbTeQETI4u9okOAPDvSscEa5pVT
          oss:
            endpoint: oss-cn-guangzhou.aliyuncs.com
            bucket: gulimall-tangzhi
      application:
        name: gulimall-third-party
    server:
      port: 30000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • ④. 网关的设置
    spring:
      cloud:
        gateway:
          routes:
            - id: third_party_route
              uri: lb://gulimall-third-party
              predicates:
                - Path=/api/thirdparty/**
              filters:
                - RewritePath=/api/thirdparty/(?>/?.*), /$\{segment}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • ⑤. 对gulimall-third-party进行功能测试
    @Slf4j
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class GulimallThirdPartyApplicationTests {
        @Autowired
        OSSClient ossClient;
        @Test
        public void uploadCloudAlibaba()throws Exception{
            // 填写本地文件的完整路径。如果未指定本地路径'则默认从示例程序所属项目对应本地路径中上传文件流。
            InputStream inputStream = new FileInputStream("C:\\Users\\Administrator\\Desktop\\car2.jpg");
            // 依次填写Bucket名称(例如examplebucket)和Object完整路径(例如exampledir/exampleobject.txt)。Object完整路径中不能包含Bucket名称。
            ossClient.putObject("gulimall-tangzhi", "car3.jpg", inputStream);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    ⑦. 服务端签名后直传

    • ①. 服务端签名后直传

    • ②. 背景
      采用JavaScript客户端直接签名(参见JavaScript客户端签名直传)时’AccessKey ID和AcessKey Secret会暴露在前端页面’因此存在严重的安全隐患。因此’OSS提供了服务端签名后直传的方案。

    • ③. 流程介绍
      在这里插入图片描述

    • ④. 编写核心controller
      http://localhost:88/api/thirdparty/oss/policy

    @RestController
    public class OssController {
    
        @Autowired
        OSS ossClient;
    
        @Value("${spring.cloud.alicloud.oss.endpoint}")
        private String endpoint;
        @Value("${spring.cloud.alicloud.oss.bucket}")
        private String bucket;
    
        @Value("${spring.cloud.alicloud.access-key}")
        private String accessId;
    
        @RequestMapping("/oss/policy")
        public R policy() {
            //https://gulimall-hello.oss-cn-beijing.aliyuncs.com/hahaha.jpg
            String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
            // callbackUrl为 上传回调服务器的URL'请将下面的IP和Port配置为您自己的真实信息。
    //        String callbackUrl = "http://88.88.88.88:8888";
            String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
            String dir = format + "/"; // 用户上传文件时指定的前缀。
    
            Map<String, String> respMap = null;
            try {
                long expireTime = 30;
                long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
                Date expiration = new Date(expireEndTime);
                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());
            }
            return R.ok().put("data",respMap);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    在这里插入图片描述在这里插入图片描述

    ⑧. 结合前端实现文件直传

    • ①. 这里提供了三个js文件,直接导入项目即可
    1. policy.js封装一个Promise’发送/thirdparty/oss/policy请求。vue项目会自动加上api前缀
    2. multiUpload.vue多文件上传。要改’改方式如下
    3. singleUpload.vue单文件上传。要替换里面的action中的内容。
      action=“http://gulimall-tangzhi.oss-cn-guangzhou.aliyuncs.com”
    <template> 
      <div>
        <el-upload
          action="http://gulimall-tangzhi.oss-cn-guangzhou.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 => {
                _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;
                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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    <template>
      <div>
        <el-upload
          action="http://gulimall-tangzhi.oss-cn-guangzhou.aliyuncs.com"
          :data="dataObj"
          list-type="picture-card"
          :file-list="fileList"
          :before-upload="beforeUpload"
          :on-remove="handleRemove"
          :on-success="handleUploadSuccess"
          :on-preview="handlePreview"
          :limit="maxCount"
          :on-exceed="handleExceed"
        >
          <i class="el-icon-plus"></i>
        </el-upload>
        <el-dialog :visible.sync="dialogVisible">
          <img width="100%" :src="dialogImageUrl" alt />
        </el-dialog>
      </div>
    </template>
    <script>
    import { policy } from "./policy";
    import { getUUID } from "@/utils";
    export default {
      name: "multiUpload",
      props: {
        //图片属性数组
        value: Array,
        //最大上传图片数量
        maxCount: {
          type: Number,
          default: 30
        }
      },
      data() {
        return {
          dataObj: {
            policy: "",
            signature: "",
            key: "",
            ossaccessKeyId: "",
            dir: "",
            host: "",
            uuid: ""
          },
          dialogVisible: false,
          dialogImageUrl: null
        };
      },
      computed: {
        fileList() {
          let fileList = [];
          for (let i = 0; i < this.value.length; i++) {
            fileList.push({ url: this.value[i] });
          }
    
          return fileList;
        }
      },
      mounted() {},
      methods: {
        emitInput(fileList) {
          let value = [];
          for (let i = 0; i < fileList.length; i++) {
            value.push(fileList[i].url);
          }
          this.$emit("input", value);
        },
        handleRemove(file, fileList) {
          this.emitInput(fileList);
        },
        handlePreview(file) {
          this.dialogVisible = true;
          this.dialogImageUrl = file.url;
        },
        beforeUpload(file) {
          let _self = this;
          return new Promise((resolve, reject) => {
            policy()
              .then(response => {
                console.log("这是什么${filename}");
                _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;
                resolve(true);
              })
              .catch(err => {
                console.log("出错了...", err);
                reject(false);
              });
          });
        },
        handleUploadSuccess(res, file) {
          this.fileList.push({
            name: file.name,
            // url: this.dataObj.host + "/" + this.dataObj.dir + "/" + file.name; 替换${filename}为真正的文件名
            url:
              this.dataObj.host +
              "/" +
              this.dataObj.key.replace("${filename}", file.name)
          });
          this.emitInput(this.fileList);
        },
        handleExceed(files, fileList) {
          this.$message({
            message: "最多只能上传" + this.maxCount + "张图片",
            type: "warning",
            duration: 1000
          });
        }
      }
    };
    </script>
    <style></style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    import http from '@/utils/httpRequest.js'
    export function policy() {
       return  new Promise((resolve,reject)=>{
            http({
                url: http.adornUrl("/thirdparty/oss/policy"),
                method: "get",
                params: http.adornParams({})
            }).then(({ data }) => {
                resolve(data);
            })
        });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • ②. 点击文件上传,出现了跨域,在oss官方文档有强调说明,一定要设置跨越
      在这里插入图片描述在这里插入图片描述
      在这里插入图片描述

    • ③. 显示图片

    <el-table-column prop="logo" header-align="center" align="center" label="品牌logo地址">
        <template slot-scope="scope">
            <!-- 自定义表格+自定义图片 -->
            <img :src="scope.row.logo" style="width: 100px; height: 80px" />
        </template>
    </el-table-column>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    c++ trivial, standard layout和POD类型解析
    Opencv——颜色模型+通道分离与合并
    Jetpack系列 -- ViewBinding应用
    【vue】AntDV组件库中a-upload实现文件上传:
    python 蓝桥杯之并查集
    HashMap线程不安全问题以及解决方法
    Java自学第2课:Java语言基础知识要点
    为什么if-else会影响我的代码的复杂度
    java基于微信小程序的电影院购票选座 uniapp 小程序
    CPU性能优化——“瑞士军刀“
  • 原文地址:https://blog.csdn.net/TZ845195485/article/details/126797082