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

article/2025/10/4 23:18:51

微信小程序使用七牛云存储

    • 导读
    • 开发前的准备
      • 七牛云配置
      • 微信小程序测试号配置
      • java配置-spring-boot
    • 正式开始
      • java端代码
        • 七牛云工具类编写
        • 响应类编写
        • 七牛云响应结果
        • 获取token的控制器
      • 小程序代码
        • 七牛云工具类
        • 工具类的调用
    • 总结
    • 查阅资料
      • 七牛云

导读

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

开发前的准备

七牛云配置

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

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

微信小程序测试号配置

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

java配置-spring-boot

application.yml配置

qiniu:ak: 七牛云AKsk: 七牛云SKdomain: 外链域名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;@Autowiredpublic void setAuth(@Value("${qiniu.ak}")String accessKey,@Value("${qiniu.sk}") String secretKey){QiniuUtil.auth = Auth.create(accessKey, secretKey);QiniuUtil.bucketManager = new BucketManager(auth, configuration);}//    获取一个不会过期的,限定空间名称的tokenpublic static String getToken(){return auth.uploadToken(bucket);}
//    获取一个限定时间,限定空间,限定文件名称的tokenpublic static String getToken(String bucket,String key){return auth.uploadToken(bucket,key,1800,new StringMap());}
//    获取限定时间,限定空间,限定前缀的的tokenpublic 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);
//        是否限定前缀-1putPolicy.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 {@Autowiredprivate RedisUtil redisUtil;@Autowiredprivate 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获取tokenfunction 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);}})}// 刷新tokenfunction 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) {//封装promisereturn new Promise((resolve, reject) => {// 过滤tokenif(!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});// 拿到后台返回的keylet 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官方文档.


http://chatgpt.dhexx.cn/article/I0ctr8ix.shtml

相关文章

微信小程序开发前端基础知识

文章目录 一、简介1、是什么2、为什么 二、准备工作1、环境准备1.1、注册账号1.2、获取APPID1.3、开发工具 2、创建微信小程序 三、组件1、目录及其作用介绍2、页面操作3、view 块级元素4、<navigator>导航跳转5、scroll-view滚动6、text 行标签7、swiper 轮播8、常用表单…

微信小程序——图片识别

我的微信小程序 期末大作业——基于百度大脑API的图片识别小程序 具体实现了动物识别、植物识别、车辆识别 三个功能 实验源码已经放到了我的GitHub&#xff0c;欢迎测试修改 GitHub仓库地址&#xff1a;https://github.com/ZHJ0125/ImageMaster 备用码云仓库地址&#xff1a;h…

微信小程序使用云开发

微信小程序使用云开发 1.序言2.初识云开发3.环境搭建4.正式使用5.使用感受6.结语 1.序言 最近给一位即将毕业的同学做了一个毕设(需求是一个小程序)&#xff0c;最开始我是使用自身最为熟悉的语言(Java) 进行编写的后端接口。然后做了几天&#xff0c;哪怕最熟悉&#xff0c;但…

微信小程序学习笔记

1. 小程序简介 小程序是一种全新的连接用户与服务的方式&#xff0c;它可以在微信内被便捷地获取和传播&#xff0c;同时具有出色的使用体验。 2.小程序运行环境 微信小程序API文档 boolean wx.canIUse(string schema) | 微信开放文档https://developers.weixin.qq.com/minipr…

微信小程序 audio 音频 组件

完整微信小程序(Java后端) 技术贴目录清单页面&#xff08;必看&#xff09; 音频。1.6.0版本开始&#xff0c;该组件不再维护。建议使用能力更强的 wx.createInnerAudioContext 接口 属性类型默认值必填说明最低版本idstring否audio 组件的唯一标识符1.0.0srcstring否要播放…

微信小程序三级分类

今天&#xff0c;在做一个电商小程序的分类页面&#xff0c;要实现三级分类。首先&#xff0c;先上图。 要完成这样一个功能&#xff0c;前端的界面就不说了&#xff0c;具体说说怎么实现的吧&#xff0c;说复杂也挺复杂的&#xff0c;说简单只要会了思路就不难了。其实思路就…

微信小程序如何获取数组下标

我们在写代码的时候我们经常会用到获取数组下标的方法&#xff0c;我们知道java通常是用for循环&#xff0c;i,输出i就出来了&#xff0c;那对于小程序该怎么实现呢&#xff0c;首先我们会想到直接用index,但是这种方法是不可行的。 1.首先要在js文件里写一个方法&#xff0c;…

Maven项目无法使用JSONObject.fromObject方法的解决方案

JSONArray jsonArray JSONArray.fromObject (arrayStr); 解决方案 导包依赖 import net.sf.json.JSONObject;<!-- JSONObject对象依赖的jar包 --> <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils<…

Cannot deserialize value of type `java.lang.Integer` from Object value (token `JsonToken.START_OBJEC

错误信息&#xff1a;org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type java.lang.Integer from Object value (token JsonToken.START_OBJECT); nested exception is com.fasterxml.jackson.databin…

cannot deserialize from Object value (no delegate- or property-based Creator) 解决方法

问题描述 直接上图 报错 cannot deserialize from Object value (no delegate- or property-based Creator) 无法从Object值反序列化&#xff08;没有基于委托或属性的创建者&#xff09; 原因分析&#xff1a; 返回的pojo类&#xff0c;里面添加了一个全参构造函数&#x…

JsonArray.fromObject()将集合转换成字符串(案例学习)

【辰兮要努力】&#xff1a;hello你好我是辰兮&#xff0c;很高兴你能来阅读&#xff0c;昵称是希望自己能不断精进&#xff0c;向着优秀程序员前行&#xff01; 博客来源于项目以及编程中遇到的问题总结&#xff0c;偶尔会有读书分享&#xff0c;我会陆续更新Java前端、后台、…

JSONObject没有fromObject方法(Json lib 库的使用)

刚开始还不知道为啥&#xff0c;最后到 jsonlib 网站上查看了原因&#xff0c;这个是连接地址 Json-lib comes in two flavors, depending on the jdk compatibility. json-lib-x.x-jdk13 is compatible with JDK 1.3.1 and upwards. json-lib-x.x-jdk15 is compatible with J…

关于JSONObject.fromObject方法报错解决方法

最近在学习web开发时&#xff0c;遇到了这样的一个报错&#xff1a; 查了很久才发现错误。 解决方案&#xff1a; 1、查看架包 一共是6个架包 下面是IDEA环境添加架包语句&#xff1a; <dependency><groupId>commons-beanutils</groupId><artifactId&…

JSONArray.fromObject(str)

com.android.builder.dexing.DexArchiveMergerException: Unable to merge dex 根源 所在 引入的jar包重复了 &#xff01; 本次问题场景 &#xff1a; 使用 json 解析 [{"num":"D30","data":"23.6"},{"num":"D…

JSONObject.fromObject 日期类型转换问题

今天在开发的时候遇到的问题&#xff1a; 由于需要调用rest服务&#xff0c;所以将dto对象转换为JSON的时候出现了日期格式不正确的问题&#xff1a; 首先查看接收的DTO&#xff1a; 由于接口需要以数组的方式传输&#xff1a; JSONArray jsonArray array.fromObject ( Arra…

JSONObject.fromObject 找不到这个方法或是报错

本人是springboot快速创建项目生成&#xff0c;默认导入springboot json.jar。 JSONObject.fromObject 方法找不到。 解决&#xff1a;在pom依赖加入 <dependency><groupId>net.sf.json-lib</groupId><artifactId>json-lib</artifactId><ver…

微信接口报错:40163

场景&#xff1a;当使用H5做微信授权时&#xff0c;微信服务器返回错误信息{"errcode":40163,"errmsg":"code been used, hints: [ req_id: nkeen7aLRa-tGQn4 ]"}&#xff0c;从返回的errmsg中可以看出是code被使用过。 结论&#xff1a;微信网…

解决微信登录出现{errcode:40163,errmsg:code been used, hints: [ req_id: jEFDVY4ce-jz9NSA ]} (前提是使用友盟分享)

记录一下&#xff0c;记录一下。 &#xff08;真的想搞洗友盟&#xff09; 前提是接入友盟分享SDK。 错误信息 {"errcode":40163,"errmsg":"code been used, hints: [ req_id: qgFD07aLRa-xgHwXa ]"} 就是这个&#xff0c;40163 、code been u…

微信公众号网页授权40163问题【php】

微信公众号网页授权40163问题 tp5为例&#xff0c;emmmm…一直报40163或40029问题&#xff0c;翻遍了各大网站都没找到合适我的办法。 如图&#xff1a; 解决之后如图&#xff1a; 因为重定向所以请求了两次code&#xff0c;所以一直报40163错误。所以&#xff0c;我改了改代…

微信小程序报错 errcode:40163,errmsg:code been used

最近刚开始学习小程序,刚解决了一个前后端数据传递的问题,成功将用户信息存储到数据库,然后又遇到一个新的问题. 问题: 我使用getUserInfo来获取用户信息的,然而获取的信息里是没有唯一标识的,都无法作为主键,我后端是通过idWorker随机生成的id. 没错,问题就是数据库数据会重复…