在开发项目的时候,经常会用到上传图片的功能,如果把图片全都存放在项目路径下,会导致项目越来越臃肿,因此可以考虑把图片上传交给第三方处理,此处采用七牛云进行图片存储。
经过测试,通过七牛云获取图片确实比直接通过自己的服务器获取的速度要快得多。
上传图片的方式有两种:
通过服务器,将文件传到服务端,由服务端上传到七牛云
通过前端js,将文件直接上传到七牛云
两种方式都可以完成上传,但是前者还需占用服务端的带宽来上传文件,然后再由服务端上传;而后者仅占用客户端的资源,这样可以减轻服务端的压力。
本文主要介绍前端上传和后端上传两种方法
依赖
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>7.1.1</version>
</dependency>
前端上传
步骤:前端通过服务端请求
token
,然后再通过七牛云提供的接口qiniu.upload进行上传,成功后取得hash
和key
。
html
<html>
<script type="text/javascript" src="js/jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="js/qiniu.min.js"></script>
<script type="text/javascript">
$(function () {
$("#upload").on("click", function () {
var obj = $("#file");
var fileName = obj.val(); //上传的本地文件绝对路径
var suffix = fileName.substring(fileName.lastIndexOf("."),fileName.length);//后缀名
var file = obj.get(0).files[0]; //上传的文件
var size = file.size > 1024 ? file.size / 1024 > 1024 ? file.size / (1024 * 1024) > 1024 ? (file.size / (1024 * 1024 * 1024)).toFixed(2) + 'GB' : (file.size
/ (1024 * 1024)).toFixed(2) + 'MB' : (file.size
/ 1024).toFixed(2) + 'KB' : (file.size).toFixed(2) + 'B'; //文件上传大小
//七牛云上传
$.ajax({
type:'post',
url: "/QiniuUpToken",
data:{"suffix":suffix},
dataType:'json',
success: function(result){
if(result.success == 1){
var observer = { //设置上传过程的监听函数
next(result){ //上传中(result参数带有total字段的 object,包含loaded、total、percent三个属性)
Math.floor(result.total.percent);//查看进度[loaded:已上传大小(字节);total:本次上传总大小;percent:当前上传进度(0-100)]
},
error(err){ //失败后
alert(err.message);
},
complete(res){ //成功后
// ?imageView2/2/h/100:展示缩略图,不加显示原图
// ?vframe/jpg/offset/0/w/480/h/360:用于获取视频截图的后缀,0:秒,w:宽,h:高
$("#image").attr("src",result.domain+result.imgUrl+"?imageView2/2/w/400/h/400/q/100");
}
};
var putExtra = {
fname: "", //原文件名
params: {}, //用来放置自定义变量
mimeType: null //限制上传文件类型
};
var config = {
region:qiniu.region.z2, //存储区域(z0:代表华东;z2:代表华南,不写默认自动识别)
concurrentRequestLimit:3 //分片上传的并发请求量
};
var observable = qiniu.upload(file,result.imgUrl,result.token,putExtra,config);
var subscription = observable.subscribe(observer); // 上传开始
// 取消上传
// subscription.unsubscribe();
}else{
alert(result.message); //获取凭证失败
}
},error:function(){ //服务器响应失败处理函数
alert("服务器繁忙");
}
});
})
})
</script>
<body>
<input type="file" name="image" id="file" accept="image/*">
<input type="button" id="upload" value="upload">
<img id="image" src="#" alt="">
</body>
</html>
controller(用于生成上传凭证)
@Controller
public class QiniuUpload {
// ******的内容需要查看七牛云账号的相关信息
private static final String accessKey = "******"; //访问秘钥
private static final String secretKey = "******"; //授权秘钥
private static final String bucket = "******"; //存储空间名称
private static final String domain = "******"; //外链域名
/**
* 七牛云上传生成凭证
*
* @throws Exception
*/
@RequestMapping("/QiniuUpToken")
@ResponseBody
public Map<String, Object> QiniuUpToken(@RequestParam String suffix) throws Exception{
Map<String, Object> result = new HashMap<String, Object>();
try {
//验证七牛云身份是否通过
Auth auth = Auth.create(accessKey, secretKey);
//生成凭证
String upToken = auth.uploadToken(bucket);
result.put("token", upToken);
//存入外链默认域名,用于拼接完整的资源外链路径
result.put("domain", domain);
// 是否可以上传的图片格式
/*boolean flag = false;
String[] imgTypes = new String[]{"jpg","jpeg","bmp","gif","png"};
for(String fileSuffix : imgTypes) {
if(suffix.substring(suffix.lastIndexOf(".") + 1).equalsIgnoreCase(fileSuffix)) {
flag = true;
break;
}
}
if(!flag) {
throw new Exception("图片:" + suffix + " 上传格式不对!");
}*/
//生成实际路径名
String randomFileName = UUID.randomUUID().toString() + suffix;
result.put("imgUrl", randomFileName);
result.put("success", 1);
} catch (Exception e) {
result.put("message", "获取凭证失败,"+e.getMessage());
result.put("success", 0);
} finally {
return result;
}
}
}
后端上传
七牛云上传文件工具类
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import com.qiniu.util.Base64;
import com.qiniu.util.StringMap;
import com.qiniu.util.UrlSafeBase64;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
/**
* 七牛云上传文件工具类
*/
public class QiniuCloudUtil {
// 设置需要操作的账号的AK和SK
private static final String ACCESS_KEY = "你的ACCESS_KEY";
private static final String SECRET_KEY = "你的SECRET_KEY";
// 要上传的空间
private static final String bucketname = "你的空间名称";
// 密钥
private static final Auth auth = Auth.create(ACCESS_KEY, SECRET_KEY);
private static final String DOMAIN = "你的图片上传路径";
private static final String style = "自定义的图片样式";
public static String getUpToken() {
return auth.uploadToken(bucketname, null, 3600, new StringMap().put("insertOnly", 1));
}
// 普通上传
public static String upload(String filePath, String fileName) throws IOException {
// 创建上传对象
UploadManager uploadManager = new UploadManager();
try {
// 调用put方法上传
String token = auth.uploadToken(bucketname);
if(StringUtils.isEmpty(token)) {
System.out.println("未获取到token,请重试!");
return null;
}
Response res = uploadManager.put(filePath, fileName, token);
// 打印返回的信息
System.out.println(res.bodyString());
if (res.isOK()) {
Ret ret = res.jsonToObject(Ret.class);
//如果不需要对图片进行样式处理,则使用以下方式即可
//return DOMAIN + ret.key;
return DOMAIN + ret.key + "?" + style;
}
} catch (QiniuException e) {
Response r = e.response;
// 请求失败时打印的异常的信息
System.out.println(r.toString());
try {
// 响应的文本信息
System.out.println(r.bodyString());
} catch (QiniuException e1) {
// ignore
}
}
return null;
}
//base64方式上传
public static String put64image(byte[] base64, String key) throws Exception{
String file64 = Base64.encodeToString(base64, 0);
Integer len = base64.length;
//华北空间使用 upload-z1.qiniu.com,华南空间使用 upload-z2.qiniu.com,北美空间使用 upload-na0.qiniu.com
String url = "http://upload.qiniu.com/putb64/" + len + "/key/"+ UrlSafeBase64.encodeToString(key);
RequestBody rb = RequestBody.create(null, file64);
Request request = new Request.Builder()
.url(url)
.addHeader("Content-Type", "application/octet-stream")
.addHeader("Authorization", "UpToken " + getUpToken())
.post(rb).build();
//System.out.println(request.headers());
OkHttpClient client = new OkHttpClient();
okhttp3.Response response = client.newCall(request).execute();
System.out.println(response);
//如果不需要添加图片样式,使用以下方式
//return DOMAIN + key;
return DOMAIN + key + "?" + style;
}
// 普通删除(暂未使用以下方法,未测试)
public static void delete(String key) throws IOException {
// 实例化一个BucketManager对象
BucketManager bucketManager = new BucketManager(auth);
// 此处的33是去掉:http://ongsua0j7.bkt.clouddn.com/,剩下的key就是图片在七牛云的名称
key = key.substring(33);
try {
// 调用delete方法移动文件
bucketManager.delete(bucketname, key);
} catch (QiniuException e) {
// 捕获异常信息
Response r = e.response;
System.out.println(r.toString());
}
}
class Ret {
public long fsize;
public String key;
public String hash;
public int width;
public int height;
}
}
controller
@ResponseBody
@RequestMapping(value="/uploadImg", method=RequestMethod.POST)
public ResultInfo uploadImg(@RequestParam MultipartFile image, HttpServletRequest request) {
ResultInfo result = new ResultInfo();
if (image.isEmpty()) {
result.setCode(400);
result.setMsg("文件为空,请重新上传");
return result;
}
try {
byte[] bytes = image.getBytes();
String imageName = UUID.randomUUID().toString();
try {
//使用base64方式上传到七牛云
String url = QiniuCloudUtil.put64image(bytes, imageName);
result.setCode(200);
result.setMsg("文件上传成功");
result.setInfo(url);
} catch (Exception e) {
e.printStackTrace();
}
} catch (IOException e) {
result.setCode(500);
result.setMsg("文件上传发生异常!");
} finally {
return result;
}
}