前言
该功能系在公司开发的过程中写出,做个记录,包括七牛云的文件服务器直传、删除、确认文件存在以及客户端的携带凭证上传,更多关于七牛的详细说明,魔法变量参数值意义,见下方七牛官方文档。
1.七牛官方Java文档
https://developer.qiniu.com/kodo/1239/java
2.后端接口
2.1. springboot添加依赖
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>[7.7.0, 7.7.99]</version>
</dependency>
2.2. 获取密钥
https://portal.qiniu.com/user/key
2.3. 添加yml配置信息
qiniu:
accessKey: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
secretKey: sssssssssssssssssssssssssssssssssssssssss
bucket: bbbbbbbbb # 创建的存储空间名 https://portal.qiniu.com/kodo/bucket
path: https://img.?????.com/ # 对应存储空间的访问域名
expireSeconds: 1800 #policy过期时间 秒
2.4. 创建配置文件
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Data
@Component
@Configuration
@ConfigurationProperties(prefix = "qiniu")
public class QiniuConfig {
private String accessKey;
private String secretKey;
private String bucket;
private String path;
private Long expireSeconds;
/**
* 华东机房
*/
@Bean
public com.qiniu.storage.Configuration qnConfig() {
return new com.qiniu.storage.Configuration(Region.region0());
}
/**
* 构建一个七牛上传工具实例
*/
@Bean
public UploadManager uploadManager() {
return new UploadManager(qnConfig());
}
/**
* 认证信息实例
*
* @return
*/
@Bean
public Auth auth() {
return Auth.create(accessKey, secretKey);
}
/**
* 构建七牛空间管理实例
*/
@Bean
public BucketManager bucketManager() {
return new BucketManager(auth(), qnConfig());
}
}
2.5. service层
import com.alibaba.fastjson.JSONObject;
import com.qiniu.common.QiniuException;
import com.qiniu.storage.model.FetchRet;
import com.qiniu.storage.model.FileInfo;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.Map;
public interface FileService {
//删除七牛云文件
Boolean deleteFile(String key);
//检查文件是否存在于七牛云
FileInfo checkFile(String key);
//服务本地上传图片,需要指定path路径
Map<String,String> uploadImg(MultipartFile files,String path);
//抓取网络资源到空间
FetchRet fetchNetSource(NetAddress target);
//七牛云本地上传方法本体
Map uploadFile(File file,String filePath,String fileName) throws QiniuException;
//前端上传凭证
JSONObject getQiniuPolicy();
}
2.6. service实现
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.storage.model.FetchRet;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import com.wenhu.app.config.QiniuConfig;
import com.wenhu.app.enums.ExceptionEnum;
import com.wenhu.app.exception.WenHuException;
import com.wenhu.app.service.FileService;
import com.wenhu.app.util.MultipartFileToFile;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@Service
@Slf4j
public class ImpFileService implements FileService {
@Autowired
private UploadManager uploadManager;
@Autowired
private BucketManager bucketManager;
@Autowired
private Auth auth;
@Autowired
private QiniuConfig qiniuConfig;
private String getUploadToken() {
return this.auth.uploadToken(qiniuConfig.getBucket(), null, 3600, null);
}
//删除
@Override
public Boolean deleteFile(String key) {
if(checkFile(key)==null){
return true;
}else{
try {
bucketManager.delete(qiniuConfig.getBucket(), key);
return true;
} catch (QiniuException e) {
log.error(e.getMessage());
throw new WenHuException(ExceptionEnum.QiNiu_Error);
}
}
}
//检查文件是否存在于七牛云
@Override
public FileInfo checkFile(String key) {
FileInfo fileInfo = null;
try {
fileInfo = bucketManager.stat(qiniuConfig.getBucket(), key);
} catch (QiniuException e) {
e.printStackTrace();
}
return fileInfo;
}
/**
* 单图单文件上传
* @param files
* @return
*/
@Override
public Map<String,String> uploadImg(MultipartFile files,String path) {
String fileName = files.getOriginalFilename();
File file = new File(path+fileName);
String imgName = "";
try {
//将MulitpartFile文件转化为file文件格式
files.transferTo(file);
//得到上传返回的结果
Map response = uploadFile(file,path,fileName);
//七牛云上图片名称hash值
//String imgHash = (String) response.get("imgHash");
//七牛云上图片Name
imgName = (String) response.get("imgName");
} catch (IOException e) {
e.printStackTrace();
}
//删除本地临时文件副本
//MultipartFileToFile.delteTempFile(file);
Map map =new HashMap();
map.put("image",imgName);
return map;
}
@Override
public FetchRet fetchNetSource(NetAddress target) {
FetchRet fetchRet = null;
try {
fetchRet = bucketManager.fetch(target.getUrl(), qiniuConfig.getBucket(), LocalDate.now()+"/"+ IdUtils.fastSimpleUUID());
} catch (QiniuException e) {
e.printStackTrace();
}
if(fetchRet == null){
throw new ServiceException("资源抓取失败", HttpStatus.NOT_FOUND);
}
/**
* TODO target.getFormat() 和 fetchRet.mineType 校验所抓取的文件是否符合预期
* 不符合 执行七牛删除文件并返回提示
*/
fetchRet.key=qiniuConfig.getPath()+fetchRet.key;
return fetchRet;
}
/* 向七牛上传文件方法的本体 */
@Override
public Map uploadFile(File file,String filePath,String fileName) throws QiniuException {
Map map = new HashMap();
LocalDateTime dateTime=LocalDateTime.now();
Response response =
this.uploadManager.put
(file,
filePath+dateTime.getYear()+""+dateTime.getMonthValue()+""+dateTime.getDayOfMonth()+""+dateTime.getHour()+""+dateTime.getMinute()+""+dateTime.getSecond()
+"/"+fileName, getUploadToken());
//解析上传的结果
DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
String imgName = putRet.key;
String imgHash = putRet.hash;
int retry = 0;
while (response.needRetry() && retry < 3) {
response = this.uploadManager.put(file, null, getUploadToken());
}
map.put("imgName", imgName);
map.put("response", response);
map.put("imgHash", imgHash);
//删除本地临时文件副本
MultipartFileToFile.delteTempFile(file);
return map;
}
@Override
public JSONObject getQiniuPolicy() {
JSONObject json = new JSONObject();
StringMap putPolicy = new StringMap();
putPolicy.put("returnBody",
"{\"key\":\"$(key)\"," +
"\"hash\":\"$(etag)\"," +
"\"bucket\":\"$(bucket)\"," +
"\"fsize\":\"$(fsize)\"," +
"\"mimeType\":\"$(mimeType)\"}");
putPolicy.put("mimeLimit","!application/json;text/plain");
json.put("token", auth.uploadToken(qiniuConfig.getBucket(), null, qiniuConfig.getExpireSeconds(), putPolicy));
json.put("url", qiniuConfig.getPath());
json.put("dirPrefix", LocalDate.now() + "/");
return json;
}
}
2.7.
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class MultipartFileToFile {
/**
* MultipartFile 转 File
*
* @param file
* @throws Exception
*/
public static File multipartFileToFile(MultipartFile file) throws Exception {
File toFile = null;
if (file.equals("") || file.getSize() <= 0) {
file = null;
} else {
InputStream ins = null;
ins = file.getInputStream();
toFile = new File(file.getOriginalFilename());
inputStreamToFile(ins, toFile);
ins.close();
}
return toFile;
}
//获取流文件
private static void inputStreamToFile(InputStream ins, File file) {
try {
OutputStream os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除本地临时文件
*
* @param file
*/
public static void delteTempFile(File file) {
if (file != null) {
File del = new File(file.toURI());
del.delete();
}
}
}
2.8. controller方法
@RestController
@RequestMapping("thirdPart")
@Api(tags = "第三方服务接口")
public class ThirdPartController {
@Autowired
FileService fileService;
@GetMapping("/qiniu/policy")
@ApiOperation("获取客户端上传七牛凭证")
public BaseResponse qiniuPolicy() {
JSONObject json = fileService.getQiniuPolicy();
return BaseResponse.ok(json);
}
@PostMapping("/qiniu/fetchNetSource")
@ApiOperation("图片或文件网络地址抓取到七牛,并返回存储七牛后文件信息")
public BaseResponse fetchNetSource(@RequestBody NetAddress target) {
return BaseResponse.ok(fileService.fetchNetSource(target.getUrl()));
}
}
import lombok.Data;
@Data
public class NetAddress {
//待抓取的 文件url
private String url;
//过滤文件格式
private String format;
}