调用七牛云对象存储,附工具类
一、前言
最近在研究七牛云的对象存储,这里做个记录。
这里通过 Java 的方式进行调用。
记得备案个域名,七牛云提供的测试域名只有三十天。
二、准备
1、注册账号
先到官网注册
2、新建空间
存储空间的名称自定义,我这里创建了一个名为 test-south 的空间
地域自行选择,一般选择离自己所在地近的
访问控制根据自己的情况选择,我这里选择私有
创建成功后会给个测试域名,期限三十天,也可以绑定自己备案过的域名
这里使用测试域名
3、查询密钥
接下来就可以写代码了
三、对接
1、查询文档
这里以Java为例,点击跳转到文档地址
2、引入依赖
这里使用 maven 依赖
<!-- https://mvnrepository.com/artifact/com.qiniu/qiniu-java-sdk -->
<!-- 七牛云 相关依赖-->
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>7.18.0</version>
</dependency>
可以通过上面的地址查询七牛云最新的依赖。
3、测试
这里只展示测试结果,完整代码放在了“四、工具类”中。
(1)、上传文件
这里上传一张名为 cat 的 jpg 图片
返回结果:
{
"hash": "FgOnal_VoXYb26Jgz_kSHlD_9Z5c",
"key": "FgOnal_VoXYb26Jgz_kSHlD_9Z5c"
}
在未定义 key 的情况下,会把 hash 值作为 key ,也就是上传文件的名称
key 比较重要,后面下载文件,查询文件信息都需要用到
试试设置 key 的情况,这里上传一张名为 dog 的 jpg 图片,设置 key 为 dog_1746500488
返回结果:
{
"hash": "Fp2JgR9tjBRN8wp62qIWPiKpeCWm",
"key": "dog_1746500488"
}
可以看到 key 就是自定义的 key ,再看看文件名称
文件名称也自定义了。
需要注意的是,如果上传多张相同的图片,不定义 key 的情况下会将前面的文件覆盖
比如我不定义 key ,再次上传名为 cat 的 jpg 图片
返回结果如下:
{
"hash": "FgOnal_VoXYb26Jgz_kSHlD_9Z5c",
"key": "FgOnal_VoXYb26Jgz_kSHlD_9Z5c"
}
可以看到 key 没有变
文件记录也没有变成三条
那定义一个 key ,再次上传试试
返回结果如下:
{
"hash": "FgOnal_VoXYb26Jgz_kSHlD_9Z5c",
"key": "cat_1746501399"
}
可以看到返回的 key 变了
文件记录也变成了三条
(2)、下载文件
这里的下载文件是返回一条文件预览链接,而不是写出文件到本地
下载文件需要上传文件返回的 key ,这里拿到上传第一个文件的 key 为例
可以看到已经返回了文件的链接
文件设置了期限,有效期为一小时,后面可以根据自己的需要修改
(3)、查询文件信息
返回结果如下:
{
"fsize": 68089,
"putTime": 17465001919308162,
"mimeType": "image/jpeg",
"type": 0,
"hash": "FgOnal_VoXYb26Jgz_kSHlD_9Z5c",
"md5": "2ba6601bc542241165c91fec3c5a88f1",
"status": 0
}
感觉这个接口的作用比较有限。。
四、工具类
1、配置类
package com.zsp.demo.qiniu.dto;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
/**
* 七牛云配置
*
* @author: gan
* @date: 2025-04-30 11:52
*/
@Data
public class QiniuConfig {
/**
* AccessKey
*/
@JSONField(name = "AccessKey")
private String AccessKey;
/**
* SecretKey
*/
@JSONField(name = "SecretKey")
private String SecretKey;
/**
* 存储空间名称
*/
@JSONField(name = "bucket")
private String bucket;
/**
* 域名
*/
@JSONField(name = "domain")
private String domain;
}
2、对象存储请求参数
package com.zsp.demo.qiniu.kodo.dto;
import lombok.Data;
import java.io.InputStream;
/**
* 七牛云 kodo 请求参数
*
* @author: gan
* @date: 2025-04-30 14:33
*/
@Data
public class QiniuKodoDto {
/**
* 本地文件路径
*/
private String localFilePath;
/**
* 文件流
*/
private InputStream inputStream;
/**
* 在七牛云中的key
*/
private String key;
}
3、对象存储工具类(重要)
其中 VerifyUtil 只是一个判空工具类,可以查看这篇博客,也可以用自己的方式判空。
package com.zsp.demo.qiniu.kodo.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.DownloadUrl;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.util.Auth;
import com.zsp.demo.qiniu.dto.QiniuConfig;
import com.zsp.demo.qiniu.kodo.dto.QiniuKodoDto;
import com.zsp.demo.utils.VerifyUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
/**
* 七牛云对象存储 工具类
*
* @author: gan
* @date: 2025-04-30 11:48
*/
public class QiniuKodoUtil {
private static final Logger log = LoggerFactory.getLogger(QiniuKodoUtil.class);
public static void main(String[] args) {
QiniuConfig config = new QiniuConfig();
config.setAccessKey("你的七牛云AccessKey");
config.setSecretKey("你的七牛云SecretKey");
config.setBucket("你的七牛云空间名称");
config.setDomain("你的七牛云文件访问域名");
// //============================上传文件 接口测试================================
// QiniuKodoDto uploadParam = new QiniuKodoDto();
// uploadParam.setLocalFilePath("/tmp/images/cat.jpg");
// JSONObject uploadFileJson = QiniuKodoUtil.uploadFile(config, uploadParam);
// System.out.println("uploadFileJson:" + uploadFileJson);
// //============================下载文件 接口测试================================
// QiniuKodoDto downloadParam = new QiniuKodoDto();
// downloadParam.setKey("FgOnal_VoXYb26Jgz_kSHlD_9Z5c");
// String fileUrl = QiniuKodoUtil.getFileUrl(config, downloadParam);
// System.out.println("fileUrl:" + fileUrl);
// //链接格式:域名/key?e=(过期时间)&token=(凭证)
// //============================查询文件信息 接口测试================================
// QiniuKodoDto queryFileInfoParam = new QiniuKodoDto();
// queryFileInfoParam.setKey("FgOnal_VoXYb26Jgz_kSHlD_9Z5c");
// JSONObject fileInfoJson = QiniuKodoUtil.getFileInfo(config, queryFileInfoParam);
// System.out.println("fileInfoJson:" + fileInfoJson);
}
/**
* 获取凭证
*
* @param config 七牛云配置
* @return 凭证
*/
private static Auth getAuth(QiniuConfig config) {
return Auth.create(config.getAccessKey(), config.getSecretKey());
}
/**
* 获取上传token
*
* @param config 七牛云配置
* @return 凭证
*/
private static String getUploadToken(QiniuConfig config) {
Auth auth = Auth.create(config.getAccessKey(), config.getSecretKey());
return auth.uploadToken(config.getBucket());
}
/**
* 上传文件
*
* @param config 七牛云配置
* @param param 上传参数
*/
private static JSONObject uploadFile(QiniuConfig config, QiniuKodoDto param) {
//上传文件需要的参数,说是分片上传
Configuration configuration = new Configuration();
configuration.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;
UploadManager uploadManager = new UploadManager(configuration);
String localFilePath = null; //本地文件路径
InputStream inputStream = null; //文件流
String token = null; //上传文件凭证
String key = null; //默认不指定key的情况下,以文件内容的hash值作为文件名
Response response = null; //上传响应结果
try {
localFilePath = param.getLocalFilePath();
inputStream = param.getInputStream();
key = param.getKey();
token = getUploadToken(config);
if (VerifyUtil.isNotEmpty(localFilePath)) {
response = uploadManager.put(localFilePath, key, token);
} else if (VerifyUtil.isNotEmpty(inputStream)) {
response = uploadManager.put(inputStream, key, token, null, null);
} else {
throw new RuntimeException("上传文件不能为空!");
}
String bodyStr = response.bodyString();
log.info("上传文件响应结果:{}", bodyStr);
return JSONObject.parseObject(bodyStr);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (VerifyUtil.isNotEmpty(inputStream)) {
try {
inputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
/**
* 查询文件链接
*
* @param config 七牛云配置
* @param param 查询参数
* @return 文件下载链接
*/
public static String getFileUrl(QiniuConfig config, QiniuKodoDto param) {
DownloadUrl downloadUrl = new DownloadUrl(config.getDomain(), false, param.getKey());
//这些中在文档中有,不是必填
//downloadUrl.setAttname("") //配置 attname
// .setFop("") //配置 fop
// .setStyle("", "", ""); //配置 style
long expireInSeconds = 3600; //1小时,可以自定义链接过期时间
long deadline = System.currentTimeMillis() / 1000 + expireInSeconds; // 带有效期
Auth auth = null;
try {
auth = getAuth(config);
//方式一
//auth.privateDownloadUrl(config.getDomain() + "/" + param.getKey(), deadline);
//方式二
return downloadUrl.buildURL(auth, deadline);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 查询文件信息
* @param config 七牛云配置
* @param param 查询参数
* @return 文件信息
*/
public static JSONObject getFileInfo(QiniuConfig config, QiniuKodoDto param) {
Auth auth = null;
BucketManager bucketManager = null;
FileInfo fileInfo = null; //文件信息
String fileInfoStr = null;
try {
auth = getAuth(config);
bucketManager = new BucketManager(auth, new Configuration()); //根据需要设置地域信息
fileInfo = bucketManager.stat(config.getBucket(), param.getKey());
fileInfoStr = JSONObject.toJSONString(fileInfo);
log.info("文件信息:{}", fileInfoStr);
return JSON.parseObject(fileInfoStr);
} catch (QiniuException e) {
throw new RuntimeException(e);
}
}
}