java后端-微信小程序使用七牛云存储

导读

最近在做一个微信小程序项目,项目中涉及到大量图片的存储,由于之前的项目用到了七牛云存储服务,所以也打算在此项目中选用七牛云作为资源站点使用。
七牛云的存储方式为:服务端转储,客户端直传,客户端token上传;
本文主要讲解客户端token上传

开发前的准备

七牛云配置

首先是创建七牛云账号,实名认证后,在控制台中开通存储服务。
在这里插入图片描述
首次使用七牛云服务的使用,会生成一对秘钥,后续需要使用此秘钥生成token。
新创建的存储空间会有一个月的免费域名使用,到期后需要使用自己的域名才能访问存储空间的内容,域名需要备案,备案时间为一到两周,如果是还未申请域名,可以提前准备。

这里使用七牛云免费提供的域名进行操作,自定义域名配置不做赘述。
在这里插入图片描述

微信小程序测试号配置

申请小程序测试号,配置服务器域名
在这里插入图片描述

java配置-spring-boot

application.yml配置

qiniu:
  ak: 七牛云AK
  sk: 七牛云SK
  domain: 外链域名
  bucket: 空间名称

pom-七牛云SDK

 <dependency>
	<groupId>com.qiniu</groupId>
	<artifactId>qiniu-java-sdk</artifactId>
	<version>7.2.29</version>
</dependency>

正式开始

java端代码

七牛云工具类编写
/**
 * 工具类中一些常量可能会在别的地方用到,所以定义为静态
 */
@Slf4j
@Component
public class QiniuUtil{
    
    public static String bucket;
    @Value("${qiniu.bucket}")
    public void setBucket(String bucket) {
        QiniuUtil.bucket = bucket;
    }
    
    public static String domain;
    @Value("${qiniu.domain}")
    public void setDomain(String domain) {
        QiniuUtil.domain = domain;
    }

    //构造一个带指定Zone对象的配置类
    public static Configuration configuration = new Configuration(Region.huanan());
    public static UploadManager uploadManager = new UploadManager(configuration);
    public static BucketManager bucketManager;
    public static Auth auth;

    @Autowired
    public void setAuth(@Value("${qiniu.ak}")String accessKey,
    					@Value("${qiniu.sk}") String secretKey){
        QiniuUtil.auth = Auth.create(accessKey, secretKey);
        QiniuUtil.bucketManager = new BucketManager(auth, configuration);
    }

//    获取一个不会过期的,限定空间名称的token
    public static String getToken(){
        return auth.uploadToken(bucket);
    }
//    获取一个限定时间,限定空间,限定文件名称的token
    public static String getToken(String bucket,String key){
        return auth.uploadToken(bucket,key,1800,new StringMap());
    }
//    获取限定时间,限定空间,限定前缀的的token
    public static String getPrefixToken(String prefix){
       return getPrefixToken(bucket,prefix);
    }
    public static String getPrefixToken(String bucket,String prefix){
        StringMap putPolicy = new StringMap();
//        限定空间及前缀
        putPolicy.put("scope",bucket+":"+prefix);
//        是否限定前缀-1
        putPolicy.put("isPrefixalScope",1);
//        设置当前时间延后半小时过期
        putPolicy.put("deadline",System.currentTimeMillis()/1000+1800);
        return auth.uploadToken(bucket, prefix, 1800, putPolicy);
    }
}
响应类编写
@Data
public class HttpResult<T> implements Serializable{

    @ApiModelProperty("返回代码")
    private Integer code;
    @ApiModelProperty("消息")
    private String msg;
    @ApiModelProperty("返回数据")
    private T data;
    public HttpResult(){ }

    public HttpResult(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    public HttpResult(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
    public static<T> HttpResult success(){
        return new HttpResult<>(200,"操作成功");
    }

//    成功,仅返回提示消息
 public static<T> HttpResult success(String msg){
        return new HttpResult<>(200,msg);
    }
//    成功,返回数据与消息
    public static<T> HttpResult success(String msg , T data){
        return new HttpResult<>(200,msg,data);
    }
//    成功,仅返回数据
    public static<T> HttpResult success(T data){
        return new HttpResult<>(200,"操作成功",data);
    }
}
七牛云响应结果
@Data
@Accessors(chain = true)
public class QiniuResult {
    private String uptoken;
    // 返回指定前缀
    private String prefixKey;

    public QiniuResult(String uptoken) {
        this.uptoken = uptoken;
    }
    public QiniuResult(String uptoken,String prefixKey) {
        this.uptoken = uptoken;
        this.prefixKey = prefixKey;
    }
}
获取token的控制器

因为多是批量上传,为了防止上传中断,导致无效图片占用空间,这里利用rabbit的消息过期机制,进行延时删除操作。
能完成延时功能的技术有很多,这里仅是为了练习rabbitMQ的使用。

@RestController
@RequestMapping("/util")
public class UtilController {
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private RabbitUtil rabbitUtil;
    @GetMapping("/getUpToken")
    @ApiOperation("获取七牛云upToken")
    public HttpResult getQiniuToken(HttpServletRequest request,
                                    @ApiParam("详情图片数量")
                                    @RequestParam(name = "size", defaultValue = "0") Integer size,
                                    @ApiParam("图片类型") @RequestParam(name = "type") String type) {
//        未收到图片数量
        if (size == 0) throw new CommonBaseException(CommonBaseErrorCode.NO_FILE_TO_UPLOAD);
//        设置消息过期时间
        MessageProperties messageProperties = new MessageProperties();
        messageProperties.setExpiration(RabbitConstant.imgDelayTime.toString());
        //        生成商品图片前缀
        String uuId16 = request.getAttribute("userId")+"/"+OtherUtil.generateShortUuid();
//        创建消息并发送
        Message message = new Message((size + "-" + uuId16).getBytes(), messageProperties);
        rabbitUtil.sendMessage(RabbitConstant.delayExchange, RabbitConstant.delayTempKey, message);
        redisUtil.set(Constant.PRODUCT_IMG_KEY+uuId16,"1",RabbitConstant.imgDelayTime+300);
//        返回uptoken和商品前缀,token按类型做前缀分类
        return HttpResult.success(new QiniuResult(QiniuUtil.getPrefixToken(type+"/"+uuId16), uuId16));
    }

小程序代码

七牛云工具类

本工具类基于七牛云社区小程序SDK改造而来

// created by gpake
(function () {

    var config = {
        // 文件上传路径,根据七牛云所处地区设置,
        uploadURL: 'https://up-z2.qiniup.com',
        // 自身空间CDN加速域名,用作返回文件路径时,拼接展示
        domain: '',
        // 上传凭证
        upToken: '',
        // 上传凭证获取地址
        upTokenURL: '',
        // 上传凭证获取函数
        upTokenFunction: null
    }
    module.exports = {
        config: config,
        init: init,
        doUpload: doUpload,
        refreshUpToken: refreshUpToken,
        uploadURLFromRegionCode:uploadURLFromRegionCode
    }
    // 在整个程序生命周期中,只需要 init 一次即可
    // 如果需要变更参数,再调用 init 即可
    function init(options) {
        config = {
            uploadURL: '',
            domain: '',
            upToken: '',
            upTokenURL: '',
            upTokenFunction: null
        };
        updateConfigWithOptions(options);
    }
    // 利用自定义属性更新七牛云配置
    function updateConfigWithOptions(options) {
        if (options.uploadURL) {
            config.uploadURL = options.uploadURL;
        } else if(options.region){
            config.uploadURL=uploadURLFromRegionCode(options.region)
        }else{
            console.error('qiniu uploader need uploadURL');
        }
        if (options.upToken) {
            config.upToken = options.upToken;
        } else if (options.uptokenURL) {
            config.upTokenURL = options.uptokenURL;
        } else if (options.uptokenFunc) {
            config.upTokenFunction = options.uptokenFunc;
        }
        if (options.domain) {
            config.domain = options.domain;
        }
    }
    // 使用配置中,获取upToken的URL获取token
    function getUpToken(callback) {
        wx.request({
            url: config.upTokenURL,
            success: function (res) {
                var token = res.data.uptoken;
                config.upToken = token;
                if (callback) {
                    callback();
                }
            },
            fail: function (error) {
                console.error(error);
            }
        })
    }
    // 刷新token
    function refreshUpToken(options) {
        config.upToken = '';
        if (options.upToken) {
            config.upToken = options.upToken;
        } else if (options.callback) {
            if (config.uptokenURL) {
                getUpToken(callback);
            } else if (config.upTokenFunction) {

            }
        } else if (config.upTokenFunction) {
            config.upToken = config.upTokenFunction(params);
        }
        if(!config.upToken || config.upToken===''){
            console.error('qiniu uploadToken is losed');
        }
    }
    // 执行上传操作,文件路径
    function doUpload(filePath, options) {
    	//封装promise
        return new Promise((resolve, reject) => {
        	// 过滤token
            if(!config.upToken || config.upToken===''){
                reject('qiniu uploadToken is losed')
            }
            //过滤文件名
            let fileName;
            if (options && options.key) {
                fileName = options.key;
            } else {
                fileName = filePath.split('//')[1];
            }
            // 封装token和文件名
            let formData = {
                'token': config.upToken,
                'key': fileName
            };
            // 使用微信上传API,上传到指定地域的域名
            wx.uploadFile({
                url: config.uploadURL,
                filePath: filePath,
                name: 'file',
                formData: formData,
                success: function (res) {
                	// 如果状态码为200 则上传成功,解析参数后返回
                    if(res.statusCode==200){
                        let dataObject = JSON.parse(res.data);
                        dataObject.imageURL = config.domain + dataObject.key;
                        resolve(dataObject);
                    }else{
                    //不然则上传失败,抛出结果
                        reject(res)
                    }
                },
                fail: function (error) {
                    reject(error)
                }
            })
        })
    }
	// 根据地域缩写获取指定地域上传域名
    function uploadURLFromRegionCode(code) {
        var uploadURL = null;
        switch (code) {
            case 'ECN'://华东地址
                uploadURL = "https://upload.qiniup.com";
                break;
            case 'NCN'://华北地址
                uploadURL = 'https://upload-z1.qiniup.com';
                break;
            case 'SCN'://华南地址
                uploadURL = 'https://upload-z2.qiniup.com';
                break;
            case 'NA'://北美地址
                uploadURL = 'https://upload-na0.qiniup.com';
                break;
            default:
                console.error('please make the region is with one of [ECN, SCN, NCN, NA]');
        }
        return uploadURL;
    }
})();
工具类的调用
const qiniuUploader = require("../../../utils/qiniuUploader");
function initQiniu(upToken) {
  var options = {
    upToken: upToken,
    uploadURL: 'https://up-z2.qiniup.com',
    domain:'http://static.***.***.***/'
  };
  qiniuUploader.init(options);
}
Page({
upload: async function(){
	// 设置类型未商品
	let type='product';
	//获取指定前缀的token,这里封装了个request工具类,做同步请求。
    let qiniuRes = await request.request("get","/util/getUpToken",{type:type,size:that.data.descImgs.length});
    // 拿到后台返回的key
    let key=qiniuRes.data.prefixKey;
    // 拼接商品前缀
    let prefixKey= type+'/'+key;
    // 使用token初始化七牛云
    initQiniu(qiniuRes.data.uptoken);
    // 上传商品封面
    let cover=that.data.coverImg;
    let coverRes = await qiniuUploader.doUpload(cover,{key:prefixKey+"/cover"+cover.substr(cover.lastIndexOf("."))});
	// 遍历上传商品详情
    let descs = that.data.descImgs;
    // 这里使用for-i循环,因为forEach会使上传方法变异步,如果没有同步需求,可以使用forEach方法
    for(let i =0,len=descs.length;i<len;i++){
      let descRes = await qiniuUploader.doUpload(descs[i],{key:prefixKey+"/desc_"+i+descs[i].substr(descs[i].lastIndexOf("."))});
    }
  }
})

总结

这里只是简单的将整个七牛云token上传流程进行梳理,关键的只是配置问题,其余代码各位可以根据自身具体需求,修改其中逻辑。

查阅资料

七牛云

七牛云token配置属性.
七牛云微信小程序SDK文档-github.
七牛云各地域上传域名.
七牛云JAVA-SDK官方文档.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值