Java中OSS儲存使用
本篇文章希望你先看完官方的API瞭解一下OSS基本語法和概念再來應該比較容易懂。
2018-02-03 更新,優化web直傳程式碼,加入註釋,新增生成資料夾、移動端臨時上傳下載、生成簽名url
2017-12-21 更新,修復上傳圖片OSS報錯,仍會返回url的BUG,操作是修改uploadFile()和uploadWebFile()方法,在catch列印日誌後return null。
2017-11-29 更新,加入web直傳需要的 StsServiceUtil,獲取檔名的改為擷取accessUrl部分,配置變數加入示例,測試類加入baseUrl,更簡潔。
一、上傳規範
主要用到了aliyun-sdk-oss,aliyun-java-sdk-core,aliyun-java-sdk-sts,joda-time等包。
1.上傳圖片主要分為本地檔案上傳(檔案流方式)和網路檔案上傳(如獲取微信頭像)上傳
1)上傳本地檔案需要引數有InputStraem流、directory目錄和fileName檔名,目錄是在專案底下的目錄,由於不建議直接在專案oss資料夾直接上傳圖片,所以目錄是一定要傳的。當傳入目錄為空時,會直接取檔名,一般是更新和替換的時候傳null。
上傳自定義格式本地檔案用upload(),png格式圖片用uploadImage()方法,mp4格式視訊用uploadVedio()方法,檔名已封裝,如果想自己生成檔名直接呼叫底層uploadFile()方法。
2)上傳網路圖片需要引數有fileUrl檔案地址、directory目錄和fileName檔名,png格式圖片用uploadWebImage()方法,檔名已封裝,如果想自定義檔名直接呼叫底層uploadWebFile()方法。
2.如果想更新檔案有兩種方式,一種是直接更新檔案,只更新內容,不更新檔名和檔案地址。另一種是替換檔案,刪除原檔案並上傳新檔案,檔名和地址同時替換。
引數傳入InputStream流和fileUrl原檔名。
1)直接更新檔案,這個可能存在瀏覽器原資料快取,呼叫updateFile()方法。
2)刪除替換檔案,由於地址更好,解決快取問題 ,呼叫replaceFile()方法。建議更新圖片用這種方式。
3.查詢檔案是否存在
引數傳入fileUrl檔案地址,通過呼叫doesObjectExist方法判斷返回值。
4.刪除檔案,分為單個刪除和批量刪除
引數傳入fileUrl檔案地址或fileUrls檔案地址集合
1.單個上傳,呼叫deleteObject方法。
2.批量上傳,呼叫deleteObjects()方法和deleteBatchObject()方法,deleteObjects()方法主要是用在同一個endpoint和bucketName ,底層是呼叫OSS的deleteObjects()方法,速度較快。
而deleteBatchObject()還適用於不同的endPoint和bucketName ,底層呼叫的是我們封裝的deleteObject()方法,由於還是一個個去刪,速度較慢。
5.Web直傳獲取簽名
注意:為了瀏覽安全,必須為bucket設定CORS。
主要用於網頁端上傳時,網頁端向服務端請求籤名,然後直接上傳,不用對服務端產生壓力。而且安全可靠。但是這個例子有一個特點,就是使用者上傳了多少檔案,使用者上傳了什麼檔案,使用者後端程式並不能馬上知道,如果想實時知曉使用者上傳了什麼檔案,可以採用上傳回調。本例子無法實現分片與斷點。
http://172.16.1.98:83/wordpress/2017/08/30/%E6%9C%8D%E5%8A%A1%E7%AB%AF%E9%85%8D%E5%90%88web%E7%AB%AF%E4%B8%8A%E4%BC%A0%E8%A7%86%E9%A2%91/
http://172.16.1.98:83/wordpress/2017/08/23/%E6%9C%8D%E5%8A%A1%E7%AB%AF%E7%AD%BE%E5%90%8D%E5%90%8E%E4%B8%8A%E4%BC%A0%E6%96%87%E4%BB%B6%E5%88%B0oss/
二、對檔案的儲存操作
注意需要修改配置!!!
注意需要修改配置!!!
注意需要修改配置!!!
package com.lemo.face.util.oss; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.aliyun.oss.OSSClient; import com.aliyun.oss.common.utils.BinaryUtil; import com.aliyun.oss.common.utils.IOUtils; import com.aliyun.oss.model.DeleteObjectsRequest; import com.aliyun.oss.model.GeneratePresignedUrlRequest; import com.aliyun.oss.model.GetObjectRequest; import com.aliyun.oss.model.ListObjectsRequest; import com.aliyun.oss.model.MatchMode; import com.aliyun.oss.model.OSSObjectSummary; import com.aliyun.oss.model.ObjectListing; import com.aliyun.oss.model.ObjectMetadata; import com.aliyun.oss.model.PolicyConditions; import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.RandomStringUtils; import org.joda.time.DateTime; import org.joda.time.LocalDateTime; import java.io.File; import java.io.InputStream; import java.net.URL; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Objects; import lombok.extern.slf4j.Slf4j; /** * @author 楊小華 * @desc 阿里檔案雲端儲存管理類 * @create 2017/11/27 14:25 **/ @Slf4j public class OSSClientUtil { static final String ACCESS_KEY_ID = ""; static final String ACCESS_KEY_SECRET = ""; /** * 使用者的儲存空間(bucket)名稱 */ static final String BUCKET_NAME = ""; /** * 對應的對映域名 */ private static final String ACCESS_URL = "http://test.rrzuzu.com/"; /** * 使用者的儲存空間所在資料中心的訪問域名 */ private static final String ENDPOINT = "oss-cn-hangzhou.aliyuncs.com"; /** * 指定專案資料夾 */ private static final String PIC_LOCATION = "face/"; /** * 加密金鑰 */ private static final String KEY = "biaoqing"; private static OSSClient ossClient; /** * @desc 靜態初始化ossClient * @author 楊小華 * @create 2017/11/25 12:44 **/ static { ossClient = new OSSClient(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET); } /** * @desc 上傳自定義格式 * @author 楊小華 * @create 2017/11/24 11:09 **/ public static String upload(InputStream is, String directory, String fileType) { String fileName = getFileName() + "." + fileType; return uploadFile(is, directory, fileName); } /** * @desc 上傳視訊指定mp4格式 * @author 楊小華 * @create 2017/11/22 15:00 **/ public static String uploadVideo(InputStream is, String directory) { String fileName = getFileName() + ".mp4"; return uploadFile(is, directory, fileName); } /** * @desc 上傳圖片指定png格式 * @author 楊小華 * @create 2017/11/22 14:59 **/ public static String uploadImage(InputStream is, String directory) { String fileName = getFileName() + ".png"; return uploadFile(is, directory, fileName); } /** * @desc 上傳網路圖片指定png格式 * @author 楊小華 * @create 2017/11/25 13:37 **/ public static String uploadWebImage(String fileUrl, String directory) { String fileName = getFileName() + ".png"; return uploadWebFile(fileUrl, directory, fileName); } /** * @desc 上傳本地檔案(檔案流上傳) * @author 楊小華 * @create 2017/11/23 19:57 **/ public static String uploadFile(InputStream is, String directory, String fileName) { String key = PIC_LOCATION + directory + "/" + fileName; if (Objects.isNull(directory)) { key = fileName; } try { ObjectMetadata objectMetadata = getObjectMetadata(is.available()); ossClient.putObject(BUCKET_NAME, key, is, objectMetadata); } catch (Exception e) { log.error(e.getMessage()); return null; } finally { IOUtils.safeClose(is); } return ACCESS_URL + key; } /** * @desc 上傳網路圖片 * @author 楊小華 * @create 2017/11/24 15:43 **/ public static String uploadWebFile(String fileUrl, String directory, String fileName) { String key = PIC_LOCATION + directory + "/" + fileName; InputStream is = null; try { Integer length = new URL(fileUrl).openConnection().getContentLength(); is = new URL(fileUrl).openStream(); ObjectMetadata objectMetadata = getObjectMetadata(length); ossClient.putObject(BUCKET_NAME, key, is, objectMetadata); } catch (Exception e) { log.error(e.getMessage()); return null; } finally { IOUtils.safeClose(is); } return ACCESS_URL + key; } /** * @desc 更新檔案:只更新內容,不更新檔名和檔案地址。 (因為地址沒變,可能存在瀏覽器原資料快取,不能及時載入新資料,例如圖片更新,請注意) * @author 楊小華 * @create 2017/11/23 20:40 **/ public static String updateFile(InputStream is, String fileUrl) { String key = getFileNameByUrl(fileUrl); return uploadFile(is, null, key); } /** * @desc 替換檔案:刪除原檔案並上傳新檔案,檔名和地址同時替換 解決原資料快取問題,只要更新了地址,就能重新載入資料) * @author 楊小華 * @create 2017/11/24 14:19 **/ public static String replaceFile(InputStream is, String fileUrl) { boolean flag = deleteObject(fileUrl); String fileName = getFileNameByUrl(fileUrl); if (!flag) { return null; } return uploadFile(is, null, fileName); } /** * @desc 查詢檔案是否存在 * @author 楊小華 * @create 2017/11/24 10:09 **/ public static boolean doesObjectExist(String key) { boolean result = false; try { //如果帶http,提取key值 if (key.indexOf("http") != -1) { key = getFileNameByUrl(key); } result = ossClient.doesObjectExist(BUCKET_NAME, key); } catch (Exception e) { log.error(e.getMessage()); } return result; } /** * @desc 刪除Object。 注意:以下所有刪除如果檔案不存在返回的是true,如果需要先判斷是否存在先呼叫doesObjectExist()方法 * @author 楊小華 * @create 2017/11/24 10:06 **/ public static boolean deleteObject(String fileUrl) { try { String key = getFileNameByUrl(fileUrl); ossClient.deleteObject(BUCKET_NAME, key); } catch (Exception e) { log.error(e.getMessage()); return false; } return true; } /** * @desc 批量刪除object(適用於相同的endpoint和bucketName) * @author 楊小華 * @create 2017/11/24 10:02 **/ public static int deleteObjects(List<String> fileUrls) { int count = 0; List<String> keys = getFileNamesByUrl(fileUrls); try { // 刪除Objects DeleteObjectsRequest deleteRequest = new DeleteObjectsRequest(BUCKET_NAME); deleteRequest.withKeys(keys); count = ossClient.deleteObjects(deleteRequest).getDeletedObjects().size(); } catch (Exception e) { log.error(e.getMessage()); } return count; } /** * @desc 批量檔案刪除(較慢, 適用於不同endpoint和bucketName) * @author 楊小華 * @create 2017/11/24 13:03 **/ public static int deleteBatchObject(List<String> fileUrls) { int count = 0; for (String url : fileUrls) { if (deleteObject(url)) { count++; } } return count; } /** * @desc web直傳獲取簽名 * @author 楊小華 * @create 2017/9/11 13:01 **/ public static Map<String, Object> getWebSign(String callbackUrl, int seconds) { Map<String, Object> data = Maps.newHashMap(); // 儲存目錄 String dir = PIC_LOCATION + "web/" + getDirectory(); //回撥內容 Map<String, String> callback = Maps.newHashMap(); callback.put("callbackUrl", callbackUrl); callback.put("callbackBody", "filename=${object}&size=${size}&mimeType=${mimeType}&height" + "=${imageInfo.height}&width=${imageInfo.width}"); callback.put("callbackBodyType", "application/x-www-form-urlencoded"); //簽名有效期30秒過期 Date expiration = DateTime.now().plusSeconds(seconds).toDate(); // 提交節點 String host = "http://" + BUCKET_NAME + "." + ENDPOINT; try { PolicyConditions policyConds = new PolicyConditions(); // 設定上傳檔案的大小限制 policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000); //指定此次上傳的檔名必須是dir變數的值開頭 policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir); String postPolicy = ossClient.generatePostPolicy(expiration, policyConds); //policy String policy = BinaryUtil.toBase64String(postPolicy.getBytes("utf-8")); //簽名 String signature = ossClient.calculatePostSignature(postPolicy); //回撥 String callbackData = BinaryUtil.toBase64String(callback.toString().getBytes("utf-8")); data.put("policy", policy); data.put("signature", signature); data.put("callback", callbackData); data.put("dir", dir); data.put("accessKeyId", ACCESS_KEY_ID); data.put("accessUrl", ACCESS_URL); data.put("host", host); data.put("expire", expiration); } catch (Exception e) { log.error(e.getMessage(), e); return null; } return data; } /** * 移動端臨時授權上傳 * * @return java.util.Map<java.lang.String,java.lang.Object> * @author 楊小華 * @date 2018/1/29 14:11 * @since 1.0.0 */ public static Map<String, Object> getSTSWrite() { Map<String, Object> data = Maps.newHashMap(); // 設定檔案目錄 String folder = PIC_LOCATION + "app/" + getDirectory(); //許可權驗證 AssumeRoleResponse.Credentials credentials = STSUtil.createSTSForPutObject(folder); Preconditions.checkState(Objects.nonNull(credentials), "許可權獲取失敗,請重試"); AssumeRoleResponse.Credentials encryptCredentials = DESUtil.encrypt(credentials, KEY); //完整檔名 data.put("oss", encryptCredentials); data.put("folder", folder); data.put("endpoint", ENDPOINT); data.put("buckName", BUCKET_NAME); data.put("accessUrl", ACCESS_URL); return data; } /** * 移動端臨時授權下載 * * @return java.util.Map<java.lang.String,java.lang.Object> * @author 楊小華 * @date 2018/1/31 15:33 * @since 1.0.0 */ public static Map<String, Object> getSTSRead() { Map<String, Object> data = Maps.newHashMap(); //許可權驗證 AssumeRoleResponse.Credentials credentials = STSUtil.createSTSForReadOnly(); Preconditions.checkState(Objects.nonNull(credentials), "許可權獲取失敗,請重試"); AssumeRoleResponse.Credentials encryptCredentials = DESUtil.encrypt(credentials, KEY); //完整檔名 data.put("oss", encryptCredentials); data.put("endpoint", ENDPOINT); data.put("buckName", BUCKET_NAME); return data; } /** * 私有型bucket,生成簽名URL * * @param key 表情地址,如face/zip/test.zip * @param seconds 多少秒後過期 * @return java.lang.String * @author 楊小華 * @date 2018/2/2 14:32 * @since 1.0.0 */ public static String getSignUrl(String key, int seconds) { //如果key值不存在 Preconditions.checkArgument(doesObjectExist(key), "key值不存在"); Date expire = DateTime.now().plusSeconds(seconds).toDate(); GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(BUCKET_NAME, key); generatePresignedUrlRequest.setExpiration(expire); URL url = ossClient.generatePresignedUrl(generatePresignedUrlRequest); return url.toString(); } /** * 單個下載檔案 * * @param key 檔案key值 * @param fileUrl 目標檔案路徑名稱 * @return boolean * @author 楊小華 * @date 2018/2/2 18:08 * @since 1.0.0 */ public static boolean getObject(String key, String fileUrl) { ObjectMetadata object = ossClient.getObject(new GetObjectRequest(BUCKET_NAME, key), new File(fileUrl)); if (Objects.nonNull(object)) { return true; } return false; } /** * 批量下載檔案 * * @param preFix 下載某個資料夾中的所有 * @param dir 目標目錄 * @return java.lang.String * @author 楊小華 * @date 2018/2/2 17:33 * @since 1.0.0 */ public static String listObject(String preFix, String dir) { // 構造ListObjectsRequest請求 ListObjectsRequest listObjectsRequest = new ListObjectsRequest(BUCKET_NAME); //Delimiter 設定為 “/” 時,羅列該資料夾下的檔案 listObjectsRequest.setDelimiter("/"); //Prefix 設為某個資料夾名,羅列以此 Prefix 開頭的檔案 listObjectsRequest.setPrefix(preFix); ObjectListing listing = ossClient.listObjects(listObjectsRequest); //如果改目錄下沒有檔案返回null if (CollectionUtils.isEmpty(listing.getObjectSummaries())) { return null; } // 取第一個目錄的key File file = new File(dir + listing.getObjectSummaries().get(0).getKey()); //判斷檔案所在本地路徑是否存在,若無,新建目錄 File fileParent = file.getParentFile(); if (!fileParent.exists()) { fileParent.mkdirs(); } // 遍歷所有Object:目錄下的檔案 for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) { //Bucket中儲存檔案的路徑 String key = objectSummary.getKey(); //下載object到檔案 ossClient.getObject(new GetObjectRequest(BUCKET_NAME, key), file); } return file.getParent(); } /** * @desc 生成檔名 * @author 楊小華 * @create 2017/11/24 11:15 **/ public static String getFileName() { return LocalDateTime.now().toString("yyyyMMddHHmmssSSS_") + RandomStringUtils .randomNumeric(6); } /** * 生成目錄 * * @return java.lang.String * @author 楊小華 * @date 2018/1/29 19:00 * @since 1.0.0 */ public static String getDirectory() { return LocalDateTime.now().toString("yyyy-MM-dd"); } /** * @desc 根據url獲取fileName * @author 楊小華 * @create 2017/11/23 20:40 **/ private static String getFileNameByUrl(String fileUrl) { int beginIndex = fileUrl.indexOf(ACCESS_URL); //針對單個圖片處理的圖片 int endIndex = fileUrl.indexOf("?"); //針對使用模板圖片處理的圖片 int endIndex2 = fileUrl.indexOf("@!"); if (beginIndex == -1) { return null; } if (endIndex != -1) { return fileUrl.substring(beginIndex + ACCESS_URL.length(), endIndex); } if (endIndex2 != -1) { return fileUrl.substring(beginIndex + ACCESS_URL.length(), endIndex2); } return fileUrl.substring(beginIndex + ACCESS_URL.length()); } /** * @desc 根據url獲取fileNames集合 * @author 楊小華 * @create 2017/11/23 20:42 **/ private static List<String> getFileNamesByUrl(List<String> fileUrls) { List<String> fileNames = Lists.newArrayList(); for (String url : fileUrls) { fileNames.add(getFileNameByUrl(url)); } return fileNames; } /** * @desc ObjectMetaData是使用者對該object的描述, * 由一系列name-value對組成;其中ContentLength是必須設定的,以便SDK可以正確識別上傳Object的大小 * @author 楊小華 * @create 2017/11/23 20:12 **/ private static ObjectMetadata getObjectMetadata(long length) { ObjectMetadata objectMetadata = new ObjectMetadata(); objectMetadata.setContentLength(length); // 被下載時網頁的快取行為 objectMetadata.setCacheControl("no-cache"); objectMetadata.setHeader("Pragma", "no-cache"); return objectMetadata; } }
臨時授權:
http://172.16.1.98:83/wordpress/2018/02/01/oss%E7%9A%84%E4%B8%B4%E6%97%B6%E6%8E%88%E6%9D%83%E8%AE%B0%E5%BD%95/
三、Junit4單元測試程式碼
package com.lemo.erp.base; import com.google.common.collect.Lists; import com.lemo.erp.plugins.oss.OSSClientUtil; import org.junit.Assert; import org.junit.Test; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util.List; import java.util.Map; /** * @author 楊小華 * @desc Oss測試類 * @create 2017/11/27 8:56 **/ public class OSSClientUtilTest { private String baseUrl = "http://pic.pingpingapp.com/duduerp/"; /** * @desc 測試上傳任意格式的檔案(如xml) * @author 楊小華 * @create 2017/11/25 12:49 **/ @Test public void testUpload() throws Exception { File file = new File("C:\\Users\\leimo\\Desktop\\test\\test.xml"); InputStream is = new FileInputStream(file); String result = OSSClientUtil.upload(is, "test", "xml"); Assert.assertTrue(result.contains("xml")); } /** * @desc 測試上傳視訊 * @author 楊小華 * @create 2017/11/25 13:28 **/ @Test public void testUploadVideo() throws Exception { File file = new File("C:\\Users\\leimo\\Desktop\\test\\test.mp4"); InputStream is = new FileInputStream(file); String result = OSSClientUtil.uploadVideo(is, "test"); Assert.assertTrue(result.contains("mp4")); } /** * @desc 測試上傳圖片 * @author 楊小華 * @create 2017/11/25 13:25 **/ @Test public void testUploadImage() throws Exception { File file = new File("C:\\Users\\leimo\\Desktop\\test\\test.jpg"); InputStream is = new FileInputStream(file); String result = OSSClientUtil.uploadImage(is, "test"); Assert.assertTrue(result.contains("png")); } /** * @desc 測試上傳網路圖片 * @author 楊小華 * @create 2017/11/24 16:01 **/ @Test public void testUploadWebImage() throws Exception { String headImg = "http://web.rrzuzu.com/WebStatic/duduerp/static/images/logo.png"; String result = OSSClientUtil.uploadWebImage(headImg, "test"); Assert.assertTrue(result.contains("png")); } /** * @desc 測試上傳網路圖片指定名稱abc.png * @author 楊小華 * @create 2017/11/25 13:41 **/ @Test public void testUploadWebFile() throws Exception { String headImg = "http://web.rrzuzu.com/WebStatic/duduerp/static/images/logo.png"; String result = OSSClientUtil.uploadWebFile(headImg, "test", "abc.png"); Assert.assertTrue(result.contains("test/abc.png")); } /** * @desc 用來測試批量刪除的圖片123.png * @author 楊小華 * @create 2017/11/25 15:20 **/ @Test public void testUploadWebFile2() throws Exception { String headImg = "http://web.rrzuzu.com/WebStatic/duduerp/static/images/logo.png"; String result = OSSClientUtil.uploadWebFile(headImg, "test", "123.png"); Assert.assertTrue(result.contains("test/123.png")); } /** * @desc 測試更新圖片 * @author 楊小華 * @create 2017/11/24 16:03 **/ @Test public void testUpdate() throws Exception { String url = baseUrl + "test/abc.png"; File file = new File("C:\\Users\\leimo\\Desktop\\test\\test.jpg"); InputStream is = new FileInputStream(file); String result = OSSClientUtil.updateFile(is, url); Assert.assertEquals(url, result); } /** * @desc 測試替換圖片 * @author 楊小華 * @create 2017/11/24 16:22 **/ @Test public void testReplaceFile() throws Exception { String url = baseUrl + "test/abc.png"; File file = new File("C:\\Users\\leimo\\Desktop\\test\\test.jpg"); InputStream is = new FileInputStream(file); String result = OSSClientUtil.replaceFile(is, url); Assert.assertEquals(url, result); } /** * @desc 測試查詢 * @author 楊小華 * @create 2017/11/24 17:31 **/ @Test public void testDoesObjectExist() throws Exception { String url = baseUrl + "test/abc.png?200"; boolean result = OSSClientUtil.doesObjectExist(url); Assert.assertTrue(result); } /** * @desc 測試單個刪除 * @author 楊小華 * @create 2017/11/24 17:33 **/ @Test public void testDeleteObject() throws Exception { String url = baseUrl + "test/abc.png"; boolean result = OSSClientUtil.deleteObject(url); System.out.println(result); Assert.assertTrue(result); } /** * @desc 測試批量刪除(同一endpoint和buckName) * @author 楊小華 * @create 2017/11/25 13:45 **/ @Test public void testDeleteObjects() throws Exception { List<String> fileUrls = Lists.newArrayList(); fileUrls.add(baseUrl + "test/abc.png"); fileUrls.add(baseUrl + "test/123.png"); int count = OSSClientUtil.deleteObjects(fileUrls); Assert.assertEquals(fileUrls.size(), count); } /** * @desc 測試批量刪除(適用不同endpoint和buckName) * @author 楊小華 * @create 2017/11/25 15:18 **/ @Test public void testDeleteBatchObject() { List<String> fileUrls = Lists.newArrayList(); fileUrls.add(baseUrl + "test/abc.png"); fileUrls.add(baseUrl + "test/123.png"); int count = OSSClientUtil.deleteBatchObject(fileUrls); Assert.assertEquals(fileUrls.size(), count); } /** * @desc 測試獲取web直傳簽名 * @author 楊小華 * @create 2017/11/27 9:38 **/ @Test public void testGetSign() { Map<String, Object> sign = OSSClientUtil.getSign(); Assert.assertTrue(sign.containsKey("endpoint")); } }
四、圖片處理
1.單張不同的圖片格式處理可採用直接在後面拼接或用程式碼去請求,如:
// 縮放 String style = "image/resize,m_fixed,w_100,h_100"; GetObjectRequest request = new GetObjectRequest(bucketName, key); request.setProcess(style); ossClient.getObject(request, new File("example-resize.jpg")); // 裁剪 style = "image/crop,w_100,h_100,x_100,y_100,r_1"; request = new GetObjectRequest(bucketName, key); request.setProcess(style); ossClient.getObject(request, new File("example-crop.jpg"));
2.多張圖片共用同一種格式,採用模板的方式,如使用者頭像框,可能有多個使用者上傳,他們的圖片格式是一樣的。
http://pic.pingpingapp.com/dudu/1511501970656.png?image/crop,w_100,h_100,x_100,y_100,r_1讓凌霄配置這種格式的模板名稱如@!crop,使用的時候在圖片後面加上這個模板名稱如http://pic.pingpingapp.com/dudu/[email protected]!crop以下是示例圖片:相關推薦
Java中OSS儲存使用
本篇文章希望你先看完官方的API瞭解一下OSS基本語法和概念再來應該比較容易懂。2018-02-03 更新,優化web直傳程式碼,加入註釋,新增生成資料夾、移動端臨時上傳下載、生成簽名url2017-12-21 更新,修復上傳圖片OSS報錯,仍會返回url的BUG,操作是修改
Java中呼叫儲存過程 -- Mybatis
Java中呼叫儲存過程 -- Mybatis public interface XXXMapper { /* * 1.沒有出參(返回值,void) 返回不了值,返回值都封裝在入參的實體類或Map中(引用型別) * 原因:存過的入參、出參都在java呼叫的入參中
在Java中呼叫儲存過程(詳細)
本文闡述了怎麼使用DBMS儲存過程。我闡述了使用儲存過程的基本的和高階特性,比如返回ResultSet。本文假設你對DBMS和JDBC已經非常熟悉,也假設你能夠毫無障礙地閱讀其它語言寫成的程式碼(即不是Java的語言),但是,並不要求你有任何儲存過程的程式設計經歷。 儲
Java中memcached 儲存 json與map相互轉化
1.Java通過memcache進行內容儲存public String getSysDict(String key) { String memKey = "_getSysDict_key_" + key; String dictionaryStr = (String) mem
java中呼叫儲存過程並傳遞list集合引數的方法
sql: CREATE OR REPLACE TYPE test as object( FID NUMBER, NUM nVARCHAR2(30), TESKID NUMBER, CID NUMBER, USERCODE nVARCHAR2(100) ) CREA
JAVA中對儲存過程的呼叫方法
一:Java如何實現對儲存過程的呼叫: A:不帶輸出引數的 ---------------不帶輸出引數的---------------------------------- create procedure getsum @n int =0<--此處為引
在java中使用儲存過程
以前用的是Statement 和 PreparedStatement 呼叫儲存過程就用到 CallableStatement cstmt =conn.prepareCall("call p(?,?,?,?)"); 宣告 一個叫p的儲存過程,需要4個引數 其中1,2為輸入引數
java 中變數儲存位置的區別
1.暫存器:最快的儲存區, 由編譯器根據需求進行分配,我們在程式中無法控制. 2. 棧:存放基本型別的變數資料和物件的引用,但物件本身不存放在棧中,而是存放在堆(new 出來的物件)或者常量池中(字串常量物件存放在常量池中。) 3. 堆:存放所有new出來的物件。
Java中物件儲存位置
1. 棧(stack)與堆(heap)都是Java用來在Ram中存放資料的地方。與C++不同,Java自動管理棧和堆,程式設計師不能直接地設定棧或堆。 2. 棧的優勢是,存取速度比堆要快,僅次於直接位於CPU中的暫存器。但缺點是,存在棧中的資料大小與生存期必須是確定的,缺乏靈活性。另外,棧資料可以共享,詳見第
淺談JAVA中字符串常量的儲存位置
數據 每一個 [] jit 返回 inf post 符號 boolean 在講述這些之前我們需要一些預備知識: Java的內存結構我們可以通過兩個方面去看待它。 一、從抽象的JVM的角度去看。相關定義請參考JVM規範:Chapter 2. The Structure o
java中資料的5種儲存位置(堆與棧)
任何語言所編寫的程式,其中的各型別的資料都需要一個儲存位置,Java中資料的儲存位置分為以下5種: 1.暫存器 最快的儲存區,位於處理器內部,但是數量極其有限。所以暫存器根據需求進行自動分配,無法直接人為控制。 2.棧記憶體 位於RAM當中,通過堆疊指標可以從處理器獲得直接支援。堆疊指標向下
Java中一維陣列和二維陣列儲存佔用記憶體大小問題
問題:在java中,一維陣列和二維陣列在資料量一樣的情況下,開闢的記憶體大小是怎樣的? 一、嘗試階段: 1、程式碼一: public class OneArrayMemory{ public static void main(String[] args){ int num1 = 1
MySql儲存過程中傳參和不傳參以及java中呼叫程式碼
資料庫表結構 1.mysql不傳參寫儲存過程 create procedure product() -- product為儲存過程名稱 begin select * from book; end 呼叫此儲存過程為 CALL product
java 中使用logback日誌,並實現日誌按天分類壓縮儲存。
以maven專案作為構建工具為例,首先引入使用logback需要的3個依賴,需要注意使用logback是需要引入slf4j-api的,因為logback是基於slf4j的 <!--logback--> <dependency> <groupId>ch.qo
java使用poi把從資料庫中取出的資料寫入到excel檔案中並儲存到指定檔案路徑
有時候我們要把從資料庫中取出的資料匯入到excel中,使取到的資料看起來更加的直觀和方便,在java中如何實現取到的資料匯入到excel中呢?以下就是使用poi工具吧資料寫入excel檔案中的解決方法: Excel表格副檔名有.xlsx和.xls兩種格式 &n
Java架構-Spring mvc+oss儲存+fileupload多檔案上傳實現SSO單點登入模板管理
之前給大家介紹了sso的相關知識點和整合方案,考慮到每個系統所屬行業的不同,這邊針對於不同行業做了一些統一的sso單點登入介面模板,使用fileupload多檔案上傳+OSS阿里雲端儲存方案。 1. 阿里雲oss儲存Utils Java程式碼 2. 阿里雲配
Java中呼叫sqlServer的儲存過程(CallableStatement)的幾種簡單情況
一、呼叫不帶引數的儲存過程 --建立儲存過程 create procedure testselect as begin select bno from book; end package com.nc.dao; import java.sql.*; public class test
String在記憶體中如何儲存(Java)
JDK1.8中JVM把String常量池移入了堆中,同時取消了“永久代”,改用元空間代替(Metaspace)java中對String物件特殊對待,所以在heap區域分成了兩塊,一塊是字串常量池(String constant pool),用於儲存java字串常量物件,另一塊用於儲存普通物件及字串物件。str
Java中順序表儲存ID的設計
我定義了一個ArrayId類,內部封裝了一個數組和對陣列的操作方法。 主要實現了陣列的自動擴容,註冊時返回一個沒有空的id,前面如果有空位置優先前面的,對空位做記錄,犧牲部分空間來提高執行效率。 下圖size就是實際儲存的大小,size和end之間是曾經刪除過的記錄。 publi
java中呼叫Oracle儲存過程時,出現異常:java.sql.SQLException: ORA-00928: 缺失 SELECT 關鍵字(已解決)
在java中呼叫Oracle儲存過程時,出現異常:java.sql.SQLException: ORA-00928: 缺失 SELECT 關鍵字 //java程式碼 @Test public void testProcedure(){