在開發項目的時候,經常會用到上傳圖片的功能,如果把圖片全都存放在項目路徑下,會導致項目越來越臃腫,因此可以考慮把圖片上傳交給第三方處理,此處採用七牛雲進行圖片存儲。
經過測試,通過七牛雲獲取圖片確實比直接通過自己的服務器獲取的速度要快得多,趕快去註冊七牛雲吧。
上傳圖片的方式有兩種:
通過服務器,將文件傳到服務端,由服務端上傳到七牛雲
通過前端js,將文件直接上傳到七牛雲
兩種方式都可以完成上傳,但是前者還需佔用服務端的帶寬來上傳文件,然後再由服務端上傳;而後者僅佔用客戶端的資源,這樣可以減輕服務端的壓力。
依賴
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>7.1.1</version>
</dependency>
前端上傳
《七牛雲官方示例》
.
《前端上傳說明文檔》
.
《qiniu.min.js下載》
步驟:前端通過服務端請求token,然後再通過七牛雲提供的接口進行上傳,成功後取得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;
}
}
注:js直接上傳七牛雲時錯誤筆記
1.xhr request failed, code: 400; response: {"error":"incorrect region, please use up-z0.qiniup.com"}
錯誤:存儲區域不正確region