七牛云OSS的使用

该文章已生成可运行项目,

图片上传

一、七牛云oss介绍

1.1 图片存储介绍

在实际开发中,我们会有很多处理不同功能的服务器。例如:

应用服务器:负责部署我们的应用

数据库服务器:运行我们的数据库

文件服务器:负责存储用户上传文件的服务器

image-20221220143849454

分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。

常见的图片存储方案:

方案一:使用nginx搭建图片服务器(最不常用)

方案二:使用开源的分布式文件存储系统,例如Fastdfs、HDFS等

方案三:使用云存储,例如阿里云、七牛云等

1.2 使用

1.2.1 注册账号
1.2.2 创建存储空间

1.2.3 开发文档

快速入门文档: https://developer.qiniu.com/kodo/1233/console-quickstart

java 开发SDK文档: https://developer.qiniu.com/kodo/1239/java

1.2.4 鉴权

鉴权:Java SDK的所有的功能,都需要合法的授权。授权凭证的签算需要七牛账号下的一对有效的Access KeySecret Key

1.2.5 工具类封装

1)添加依赖

<!--七牛云的图片上传依赖-->
<dependency>
    <groupId>com.qiniu</groupId>
    <artifactId>qiniu-java-sdk</artifactId>
    <version>7.16.0</version>
</dependency>

2)编写工具类

package com.woniuxy.portal.utils;

import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;

public class QiNiuUploadUtils {
    /**
     * 图片上传
     * @param uploadBytes
     * @param filename
     */
    public static String uploadFile(byte[] uploadBytes, String filename){
        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(Region.region2());
        cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
        //...其他参数参考类注释
        UploadManager uploadManager = new UploadManager(cfg);
        //...生成上传凭证,然后准备上传
        String accessKey = "2Zoe5PP-D0Jxf3pcIHjVzgOaVxxxx";
        String secretKey = "w4nWQuFo_0VpybJ6pnesFmOZ9xxxx";
        String bucket = "xxxx";

        //外链接域名
        String url = "http://smgw1dpx5.hn-bkt.xxxx";

        //默认不指定key的情况下,以文件内容的hash值作为文件名 文件的名称
        String key = filename;

        // 签名(密码)
        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);

        try {
            Response response = uploadManager.put(uploadBytes, key, upToken);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);

            // http://smgw1dpx5.hn-bxxxx/zs.jpg
            return url +"/" +filename;

        } catch (QiniuException ex) {
            Response r = ex.response;
            System.err.println(r.toString());
            try {
                System.err.println(r.bodyString());
            } catch (QiniuException ex2) {
                //ignore
            }
        }
        return "";
    }

    /**
     * 删除文件
     * @param fileName
     */
    public static void deleteFile(String fileName){
        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(Region.region2());
        //...其他参数参考类注释
        String accessKey = "2Zoe5PP-D0Jxf3pcIHjVzgOaVKAxxxx";
        String secretKey = "w4nWQuFo_0VpybJ6pnesFmOZ9xxxx";
        String bucket = "xxxx";
        //外链接域名

        Auth auth = Auth.create(accessKey, secretKey);
        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            bucketManager.delete(bucket, fileName);
        } catch (QiniuException ex) {
            //如果遇到异常,说明删除失败
            System.err.println(ex.code());
            System.err.println(ex.response.toString());
        }
    }
}

二、头像上传

2.1 后端上传图片开发

2.2.1 编写上传图片的控制器
package com.woniuxy.portal.controller;

import com.woniuxy.portal.utils.QiNiuUploadUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.UUID;

@RestController
@RequestMapping("/upload")
@Api(tags = "文件上传")
public class UploadController{

    // @RequestPart 接受 前端 传递过来的图片 
    @ApiOperation("文件上传")
    @PostMapping("/images")
    public ResponseEntity<String> upload(@RequestPart MultipartFile file) throws IOException {
        // 1. 获取文件名称
        String originalFilename = file.getOriginalFilename();
        // 2. 重新设置文件的名称
        String uuid = UUID.randomUUID().toString();
        // 文件的名称 = uuid + 源文件的后缀
        String substring = originalFilename.substring(originalFilename.lastIndexOf("."));
        String fileName = uuid + substring;
        fileName = fileName.replaceAll("-", "");
        // 3. 调用图片上传的工具类
        String pathUrl = QiNiuUploadUtils.uploadFile(file.getBytes(), fileName);

        // 4. 响应数据
        return ResponseEntity.ok(pathUrl);
    }

    @ApiOperation("删除图片")
    @GetMapping("/delete")
    public ResponseEntity delete(String fileName){
        QiNiuUploadUtils.deleteFile(fileName);
        return ResponseEntity.ok().build();
    }
}
2.2.2 swagger测试

注意:springmvc处理上传的文件,要想通过swagger测试,需要添加注解@RequestPart,声明是一个文件上传表单

2.2.3 图片上传优化

存在的问题

String accessKey = "xxx";
String secretKey = "xxx";
String bucket = "xxx";

七牛云的账号全部是写在代码里面的,将来要修改的话不是非常方便,而且有可能会漏掉,所以,将配置项全部移到配置文件中

1)将账号配置到配置文件中

# 七牛云账号相关配置
qiNiu:
  accessKey: xxx
  secretKey: xxx
  bucket: xxx

2)定义常量类

在common工程中定义一个常量类

package com.woniu.entity;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * 常量类,定义各种常量
 */
@Component
public class Constant {
    @Value("${qiNiu.accessKey}")
    private String accessKey;
    @Value("${qiNiu.secretKey}")
    private String secretKey;
    @Value("${qiNiu.bucket}")
    private String bucket;

    public static String ACCESSKEY;
    public static String SECRETKEY;
    public static String BUCKET;

    // 对象创建之后执行该方法
    @PostConstruct
    public void init(){
        ACCESSKEY = this.accessKey;
        SECRETKEY = this.secretKey;
        BUCKET = this.bucket;
    }
}

3)修改工具类

String accessKey = Constant.ACCESSKEY;
String secretKey = Constant.SECRETKEY;
String bucket = Constant.BUCKET;

2.2 前端上传图片开发

2.2.1 从官网拷贝组件
<script setup>
    import { ref } from 'vue'
    import { ElMessage } from 'element-plus'

    const imgUrl = ref('')

    const handleAvatarSuccess = (response) => {
        console.log(response);
        // 文件上传成功后的处理,通常是返回头像的 URL
        imgUrl.value =response;
    }
    const submitAvatar = () => {
        //提交数据
        const user = {
            username:"zs",
            age:"30",
            url:imgUrl.value
        }
        if (imgUrl.value) {
            ElMessage.success('头像修改成功'+ user.url + ",用户信息进行修改")
        } else {
            ElMessage.error('请先上传头像')
        }
    }
</script>

<template>
    <el-row class="avatar-uploader-container">
        <el-col :span="12" class="avatar-uploader-col">
            <el-upload
                    action="http://localhost:8080/upload/images"
                    class="avatar-uploader"
                    :show-file-list="false"
                    :on-success="handleAvatarSuccess">
                <img v-if="imgUrl" :src="imgUrl" class="avatar" />
                <img v-else src="@/assets/logo.png" class="default-avatar" />
            </el-upload>
            <el-button
                    type="success"
                    size="large"
                    @click="submitAvatar"
                    class="upload-button">
                上传头像
            </el-button>
        </el-col>
    </el-row>
</template>
<style scoped>
    .avatar-uploader-container {
        display: flex;
        justify-content: center;
        align-items: center;
        margin-top: 30px;
    }

    .avatar-uploader-col {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
    }

    .avatar-uploader {
        border: 2px solid #e4e7ed;
        border-radius: 50%;
        width: 120px;
        height: 120px;
        background-color: #f3f4f6;
        display: flex;
        justify-content: center;
        align-items: center;
        cursor: pointer;
        transition: border-color 0.3s ease;
    }

    .avatar-uploader:hover {
        border-color: #409eff;
    }

    .avatar {
        width: 100%;
        height: 100%;
        object-fit: cover;
        border-radius: 50%;
    }

    .default-avatar {
        width: 60%;
        height: 60%;
        object-fit: contain;
    }

    .upload-button {
        margin-top: 15px;
        background-color: #409eff;
        border-color: #409eff;
        color: white;
        border-radius: 20px;
        padding: 10px 30px;
        font-size: 16px;
        transition: background-color 0.3s ease, border-color 0.3s ease;
    }

    .upload-button:hover {
        background-color: #66b1ff;
        border-color: #66b1ff;
    }

    .upload-button:focus {
        outline: none;
    }

    .upload-button i {
        margin-right: 8px;
    }
</style>
2.2.3 修改上传成功的回调
//上传成功回调的处理方法 
const handleAvatarSuccess = (response) => {
    console.log(response);
    // 文件上传成功后的处理,通常是返回头像的 URL
    imgUrl.value =response;
}
2.2.3效果图:

image-20241105211250713

本文章已经生成可运行项目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昔我往昔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值