spring boot使用七牛雲分片上傳講解示例-upload_v2_api
阿新 • • 發佈:2022-12-02
import com.qiniu.common.QiniuException; import com.qiniu.http.Client; import com.qiniu.util.Auth; import test.com.qiniu.TempFile; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class UploadDemo { //設定好賬號的ACCESS_KEY和SECRET_KEY String ACCESS_KEY = "Access_Key"; String SECRET_KEY = "Secret_Key"; /** * 要上傳的空間對應的 urlPrefix scheme + host * host: * 華東機房(region0): up.qiniup.com 或 upload.qiniup.com * 華北機房(region1): up-z1.qiniup.com 或 upload-z1.qiniup.com * 華南機房(region2): up-z2.qiniup.com 或 upload-z2.qiniup.com * 北美機房(regionNa0): up-na0.qiniup.com 或 upload-na0.qiniup.com * 新加坡機房(regionAs0): up-as0.qiniup.com 或 upload-as0.qiniup.com * 霧儲存華東一區(regionFogCnEast1): up-fog-cn-east-1.qiniup.com 或 upload-fog-cn-east-1.qiniup.com */ String urlPrefix = "urlPrefix" // http://up.qiniup.com"; // 要上傳的空間 String bucketName = "Bucket_Name"; //上傳到七牛後儲存的檔名 String key = "my-java.png"; //金鑰配置 Auth auth = Auth.create(ACCESS_KEY, SECRET_KEY); //簡單上傳,使用預設策略,只需要設定上傳的空間名就可以了 public String getUpToken() { return auth.uploadToken(bucketName); } public static void main(String args[]) throws IOException { new UploadDemo().upload(); } public void testUpload() { String fileName = "java_api_v2_test.zip"; long fileSize = 1024 * 7 + 2341; // 單位: k File f = null; try { f = TempFile.createFile(fileSize); } catch (IOException e) { e.printStackTrace(); } fileSize *= 1024; // 單位: B /** * 一個檔案被分成多個 part,上傳所有的 part,然後在七牛雲根據 part 資訊合成檔案 * |----------------------------- file -----------------------------| * |------ part ------|------ part ------|------ part ------|... * |----- etag01 -----|----- etag02 -----|----- etag03 -----|... * allBlockCtx = [{"partNumber":1, "etag", etag01}, {"partNumber":2, "etag", etag02}, {"partNumber":3, "etag", etag03}, ...] * * 上傳過程: * 1. 呼叫 ApiUploadV2InitUpload api 建立一個 upload 任務,獲取 uploadId * 2. 重複呼叫 ApiUploadV2UploadPart api 直到檔案所有的 part 均上傳完畢, part 的大小可以不相同 * 3. 呼叫 ApiUploadV2CompleteUpload api 組裝 api * 4. ApiUploadV2InitUpload、ApiUploadV2UploadPart、ApiUploadV2CompleteUpload 等分片 V2 API的 key 需要統一(要麼有設定且相同,要麼均不設定) * * 注: * 1. partNumber 範圍是 1 ~ 10000 * 2. 除最後一個 Part 外,單個 Part 大小範圍 1 MB ~ 1 GB * 3. 如果你用同一個 PartNumber 上傳了新的資料,那麼服務端已有的這個號碼的 Part 資料將被覆蓋 */ int defaultPartSize = 1024 * 1024 * 2; RandomAccessFile file = null; try { file = new RandomAccessFile(f, "r"); } catch (IOException e) { e.printStackTrace(); } String token = getUpToken(); Configuration configuration = new Configuration(); Client client = new Client(configuration); // 1. init upload String uploadId = null; ApiUploadV2InitUpload initUploadApi = new ApiUploadV2InitUpload(client); ApiUploadV2InitUpload.Request initUploadRequest = new ApiUploadV2InitUpload.Request(urlPrefix, token) .setKey(key); try { ApiUploadV2InitUpload.Response initUploadResponse = initUploadApi.request(initUploadRequest); uploadId = initUploadResponse.getUploadId(); System.out.println("init upload:" + initUploadResponse.getResponse()); System.out.println("init upload id::" + initUploadResponse.getUploadId()); } catch (QiniuException e) { e.printStackTrace(); } // 2. 上傳檔案資料 List<Map<String, Object>> partsInfo = new ArrayList<>(); long partOffset = 0; // 塊在檔案中的偏移量 int partNumber = 1; // part num 從 1 開始 while (partOffset < fileSize) { // 1.2.1 讀取 part 資料 long partSize = fileSize - partOffset; if (partSize > defaultPartSize) { partSize = defaultPartSize; } byte[] partData = getUploadData(file, partOffset, (int) partSize); // 1.2.2 上傳 part 資料 ApiUploadV2UploadPart uploadPartApi = new ApiUploadV2UploadPart(client); ApiUploadV2UploadPart.Request uploadPartRequest = new ApiUploadV2UploadPart.Request(urlPrefix, token, uploadId, partNumber) .setKey(key) .setUploadData(partData, 0, partData.length, null); try { ApiUploadV2UploadPart.Response uploadPartResponse = uploadPartApi.request(uploadPartRequest); String etag = uploadPartResponse.getEtag(); String md5 = uploadPartResponse.getMd5(); Map<String, Object> partInfo = new HashMap<>(); partInfo.put(ApiUploadV2CompleteUpload.Request.PART_NUMBER, partNumber); partInfo.put(ApiUploadV2CompleteUpload.Request.PART_ETG, etag); partsInfo.add(partInfo); System.out.println("upload part:" + uploadPartResponse.getResponse()); } catch (QiniuException e) { e.printStackTrace(); break; } // 1.2.3 計算下一個 part 的 number partNumber += 1; partOffset += partSize; } int lastPartNum = partNumber - 1; // 獲取上傳的 part 資訊 Integer partNumberMarker = null; List<Map<String, Object>> listPartInfo = new ArrayList<>(); while (true) { ApiUploadV2ListParts listPartsApi = new ApiUploadV2ListParts(client); ApiUploadV2ListParts.Request listPartsRequest = new ApiUploadV2ListParts.Request(urlPrefix, token, uploadId) .setKey(key) .setMaxParts(2) // 此處僅為示例分頁拉去,實際可不配置使用預設值1000 .setPartNumberMarker(partNumberMarker); try { ApiUploadV2ListParts.Response listPartsResponse = listPartsApi.request(listPartsRequest); partNumberMarker = listPartsResponse.getPartNumberMarker(); listPartInfo.addAll(listPartsResponse.getParts()); System.out.println("list part:" + listPartsResponse.getResponse()); // 列舉結束 if (partNumberMarker == 0) { break; } } catch (QiniuException e) { e.printStackTrace(); break; } } System.out.println("list parts info:" + listPartInfo); // 3. 組裝檔案 String fooKey = "foo"; String fooValue = "foo-Value"; Map<String, Object> customParam = new HashMap<>(); customParam.put("x:foo", fooValue); ApiUploadV2CompleteUpload completeUploadApi = new ApiUploadV2CompleteUpload(client); ApiUploadV2CompleteUpload.Request completeUploadRequest = new ApiUploadV2CompleteUpload.Request(urlPrefix, token, uploadId, partsInfo) .setKey(key) .setFileName(fileName) .setCustomParam(customParam); try { ApiUploadV2CompleteUpload.Response completeUploadResponse = completeUploadApi.request(completeUploadRequest); System.out.println("complete upload:" + completeUploadResponse.getResponse()); } catch (QiniuException e) { e.printStackTrace(); } f.delete(); } private byte[] getUploadData(RandomAccessFile file, long offset, int size) { byte[] uploadData = new byte[size]; try { file.seek(offset); int readSize = 0; while (readSize != size) { int s = 0; try { s = file.read(uploadData, readSize, size - readSize); } catch (IOException e) { e.printStackTrace(); } if (s >= 0) { readSize += s; } else { break; } } } catch (IOException e) { uploadData = null; } return uploadData; } }