文章目录

  • OSS的开通 + 创建存储空间
  • 使用Java向OSS中存储图片
  • 使用SpringBoot+Vue+Element-ui实现图片的上传
  • 后端
  • 前端


OSS的开通 + 创建存储空间

首先到阿里云对象存储OSS官网开通对象存储OSS服务。

然后在阿里云首页点击控制台

Android 阿里 oss 流程 阿里oss怎么用_spring boot

然后点击对象存储OSS。

Android 阿里 oss 流程 阿里oss怎么用_spring boot_02

点击创建Bucket。

Android 阿里 oss 流程 阿里oss怎么用_spring boot_03

创建Bucket。
注意:这里的读写权限改为公共读。因为是简单的使用OSS,所以大部分都是默认的。

Bucket命名规则
Bucket名称在OSS范围内必须全局唯一。
只能包括小写字母、数字和短划线(-)。
必须以小写字母或者数字开头和结尾。
长度为3~63个字符。

Android 阿里 oss 流程 阿里oss怎么用_Android 阿里 oss 流程_04

上传文件。

Android 阿里 oss 流程 阿里oss怎么用_Android 阿里 oss 流程_05

先扫描文件或者是将文件拖入框中,完成之后点击上传文件。

Android 阿里 oss 流程 阿里oss怎么用_Android 阿里 oss 流程_06

下面就是上传成功后的结果。

Android 阿里 oss 流程 阿里oss怎么用_Android 阿里 oss 流程_07

使用Java向OSS中存储图片

Java操作OSS的SDK示例

导入依赖

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

编写测试用例

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
@SpringBootTest
class OssApplicationTests {
 	@Test
    void uploadOSS() {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-beijing.aliyuncs.com";
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = "***";
        String accessKeySecret = "***";
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "tests-bucket-2022";

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(new Date()) + "/";

        // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
        String objectName = format + UUID.randomUUID() + ".png";
        // 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
        // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
        String filePath= "E:\\笔记\\软件测试\\image\\_01.png";
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            InputStream inputStream = new FileInputStream(filePath);
            // 创建PutObject请求。
            ossClient.putObject(bucketName, objectName, inputStream);
        } catch (OSSException oe) {

        } catch (ClientException ce) {

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

我们可以发现上传成功!

Android 阿里 oss 流程 阿里oss怎么用_vue.js_08

使用SpringBoot+Vue+Element-ui实现图片的上传

后端

该功能后端的目录结构

Android 阿里 oss 流程 阿里oss怎么用_Android 阿里 oss 流程_09

sql语句

CREATE TABLE `pic`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `url` varchar(255)  NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
)

导入依赖

<dependencies>
   <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

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

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
	<!-- 数据源 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.8</version>
    </dependency>
	<!-- mybatis-->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.2.2</version>
    </dependency>
	<!-- mysql驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
	<!-- 小辣椒 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

application.properties的配置

# mysql的相关配置
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/csdn
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# mybatis配置
mybatis.mapper-locations=classpath:com/zhang/mapper/*.xml
mybatis.type-aliases-package=com.zhang.entity
# 打印sql语句
logging.level.com.zhang=debug

实体类

@Data
public class Picture {
    private Integer id;
    private String url;
}

dao层

@Mapper
public interface PictureDao {
   void add(Picture picture);
   List<Picture> list();
   void delete(Integer id);
}

mapper的配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhang.dao.PictureDao">
    <select id="add" parameterType="com.zhang.entity.Picture">
        insert into picture (url) values (#{url})
    </select>

    <select id="list" resultType="Picture">
        select id,url from picture
    </select>

    <delete id="delete">
        delete from picture where id = #{id}
    </delete>
</mapper>

service层

public interface PictureService {
    void add(Picture picture);
    List<Picture> list();
    void delete(Integer id);
}
@Service
public class PictureServiceImpl implements PictureService {

    @Resource
    private PictureDao pictureDao;

    @Override
    public void add(Picture picture) {
        pictureDao.add(picture);
    }

    @Override
    public List<Picture> list() {
        return pictureDao.list();
    }

    @Override
    public void delete(Integer id) {
        pictureDao.delete(id);
    }
}

controller层
实现图片上传的控制层

@RestController
public class OSSController {

    @CrossOrigin        // 跨域
    @RequestMapping("/oss")
    public Map<String,String> policy() {
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessId = "LTAI5t7Kp28TGsMHbS5YMMS9";
        String accessKey = "vbap18qeb9xEkumxLLnQTNtJoaR320";
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "oss-cn-beijing.aliyuncs.com";
        // 填写Bucket名称,例如examplebucket。
        String bucket = "tests-bucket-2022";
        // 填写Host地址,格式为https://bucketname.endpoint。
        String host = "https://" + bucket + "." + endpoint;

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

        // 创建ossClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessId, accessKey);
        Map<String, String> respMap = new LinkedHashMap<String, String>();
        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.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 respMap;
    }
}

实现图片查询添加、删除的控制层

@RestController
public class PictureController {

    @Resource
    private PictureService pictureService;

    @CrossOrigin
    @RequestMapping("/list")
    public List<Picture> list(){
        return pictureService.list();
    }

    @CrossOrigin
    @PostMapping(value = "/add")
    public void add(@RequestBody String url){
        Picture picture = new Picture();
        picture.setUrl(url);
        System.out.println(picture);
        pictureService.add(picture);
    }

    @CrossOrigin
    @RequestMapping("/delete/{id}")
    public void delete(@PathVariable Integer id){
        pictureService.delete(id);
    }
}

前端

前端使用的是vue+element-ui

实现图片上传的组件

<template>
  <el-upload
    class="upload-demo"
    :action="objData.host"
    :file-list="fileList"
    :data="objData"
    :on-success="uploadImage"
    :before-upload="ossPolicy"
    list-type="picture">
    <el-button size="small" type="primary">点击上传</el-button>
    <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
  </el-upload>
</template>

<script>
  export default {
    data() {
      return {
        fileList: [],
        objData:{
          OSSAccessKeyId:'',
          policy:'',
          Signature:'',
          key:'',   // 文件的名字
          host:'',
          dir:''
        },
        url:''
      };
    },
    methods:{
      uploadImage(response, file){	// 图片上传成功时调用的函数
        this.url = this.url + file.name;
        this.submit(this.url)
        
      },
      submit(url){		// 添加图片
        this.axios({
          method:'post',
          url:'http://localhost:8080/add',
          data:url,
          headers: {
            'Content-Type': 'application/json;charset=utf-8'
          }
        })
      },
      ossPolicy() {			// 直接上传到oss
        let _self = this;
        // 直接停止上传return false;
        // 再上传前,进行服务器签名
        return new Promise((resolve, reject) => {
          // 请求后端
          this.axios.get('http://localhost:8080/oss')
            // 当使用箭头函数  this 指向的是外层
            .then(response => {
              console.log(response)
              _self.objData.OSSAccessKeyId = response.data.accessId;
              _self.objData.policy = response.data.policy;
              _self.objData.Signature = response.data.signature;
              _self.objData.dir = response.data.dir;
              _self.objData.host = response.data.host;  // 直传 oss 的服务器地址
              _self.objData.key = response.data.dir + "${filename}";    // 文件的名字, 占位符,另一头拼接上
              this.url = response.data.host + "/" + response.data.dir
              resolve(true) // 继续上传
            })
            .catch(function (error) {
              console.log(error);
              reject(false)  // 停止上传
            })
        });
      },
      first(){			// 查询
        this.axios.get('http://localhost:8080/list')
          .then(response => {
            console.log(response)
            this.fileList = response.data
          })
          .catch(function(error) {
          })
      }
    }
  }
</script>

遍历图片的组件

<template>
  <el-table
    :data="tableData"
    style="width: 100%">
    <el-table-column
      label="序号"
      width="180">
      <template slot-scope="scope">
        <i class="el-icon-time"></i>
        <span style="margin-left: 10px">{{ scope.row.id }}</span>
      </template>
    </el-table-column>
    <el-table-column
      label="图片地址"
      width="180">
      <template slot-scope="scope">
        <el-image :src="scope.row.url"></el-image>
      </template>
    </el-table-column>
    <el-table-column label="操作">
      <template slot-scope="scope">
        <el-button
          size="mini"
          type="danger"
          @click="handleDelete(scope.$index, scope.row)">删除</el-button>
      </template>
    </el-table-column>
  </el-table>
</template>
<script>
    export default {
      name: "ListPicture",
      data() {
        return {
          tableData: [{
            id: '',
            url: ''
          }]
        }
      },
      methods: {
        handleDelete(index,row) {
          console.log(row.id);
          this.axios.get('http://localhost:8080/delete/' + row.id)
            .then(response => {
              this.first()
            })
            .catch(function(error) {
            })
        },
        first(){
          this.axios.get('http://localhost:8080/list')
            .then(response => {
              this.tableData = response.data
            })
            .catch(function(error) {
            })
        }
      },
      mounted() {
        this.first();
      }
    }
</script>

首页

<template>
  <el-container>
    <el-header height="300px">
      <ListPicture></ListPicture>
    </el-header>
    <el-main>
      <Oss></Oss>
    </el-main>
  </el-container>
</template>
<script>
  import Oss from "./Oss";
  import ListPicture from "./ListPicture";
  export default {
  name: 'HelloWorld',
  components:{Oss,ListPicture},
}
</script>