OSS SDK for Java menggunakan verifikasi MD5 dan CRC-64 untuk memastikan integritas data selama unggah, unduh, dan penyalinan objek.
Catatan penggunaan
-
Topik ini menggunakan titik akhir publik wilayah China (Hangzhou). Untuk mengakses OSS dari layanan Alibaba Cloud lainnya dalam wilayah yang sama, gunakan titik akhir internal. Untuk informasi selengkapnya mengenai wilayah dan titik akhir yang didukung, lihat Regions and Endpoints.
-
Topik ini memperoleh kredensial akses dari variabel lingkungan. Untuk informasi lebih lanjut, lihat Configure access credentials.
-
Topik ini menunjukkan cara membuat instans OSSClient dengan titik akhir OSS. Untuk konfigurasi alternatif, seperti penggunaan domain kustom atau autentikasi dengan kredensial dari Security Token Service (STS), lihat Client configuration.
Verifikasi MD5
Saat Anda menyertakan Content-MD5 dalam permintaan unggah, OSS akan membandingkan hash MD5 dari data yang diterima dengan nilai yang Anda berikan. Jika nilainya tidak cocok, OSS mengembalikan kesalahan InvalidDigest dan Anda harus mengunggah ulang objek tersebut.
Unggah multi-bagian juga mendukung verifikasi MD5. Panggil setMd5Digest di UploadPartRequest untuk mengatur hash MD5 setiap bagian.
Verifikasi MD5 didukung untuk operasi PutObject, GetObject, AppendObject, PostObject, unggah multi-bagian, dan UploadPart.
-
Konfigurasikan verifikasi MD5 dalam operasi PutObject:
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.common.comm.SignVersion; import com.aliyun.oss.common.utils.BinaryUtil; import com.aliyun.oss.model.ObjectMetadata; import java.io.ByteArrayInputStream; public class Demo { public static void main(String[] args) throws Throwable { // Pada contoh ini, titik akhir wilayah China (Hangzhou) digunakan. Tentukan titik akhir aktual Anda. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // Peroleh kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Tentukan nama bucket. Contoh: examplebucket. String bucketName = "examplebucket"; // Tentukan path lengkap objek. Jangan sertakan nama bucket dalam path lengkap. String objectName = "exampledir/object"; // Tentukan wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur wilayah menjadi cn-hangzhou. String region = "cn-hangzhou"; // Buat instans OSSClient. // Panggil metode shutdown untuk melepaskan sumber daya saat OSSClient tidak lagi digunakan. ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); try { // Unggah string. String content = "Hello OSS"; ObjectMetadata meta = new ObjectMetadata(); // Konfigurasikan verifikasi MD5. String md5 = BinaryUtil.toBase64String(BinaryUtil.calculateMd5(content.getBytes())); meta.setContentMD5(md5); ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content.getBytes()), meta); } catch (OSSException oe) { System.out.println("Terjadi OSSException, yang berarti permintaan Anda sampai ke OSS, " + "tetapi ditolak dengan tanggapan kesalahan karena suatu alasan."); System.out.println("Pesan Kesalahan:" + oe.getErrorMessage()); System.out.println("Kode Kesalahan:" + oe.getErrorCode()); System.out.println("ID Permintaan:" + oe.getRequestId()); System.out.println("Host ID:" + oe.getHostId()); } catch (ClientException ce) { System.out.println("Terjadi ClientException, yang berarti client mengalami " + "masalah internal serius saat mencoba berkomunikasi dengan OSS, " + "seperti tidak dapat mengakses jaringan."); System.out.println("Pesan Kesalahan:" + ce.getMessage()); } finally { if (ossClient != null) { ossClient.shutdown(); } } } } -
Konfigurasikan verifikasi MD5 dalam operasi unggah multi-bagian:
import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import com.aliyun.oss.ClientBuilderConfiguration; import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import com.aliyun.oss.common.auth.CredentialsProviderFactory; import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider; import com.aliyun.oss.common.comm.SignVersion; import com.aliyun.oss.common.utils.BinaryUtil; import com.aliyun.oss.model.CompleteMultipartUploadRequest; import com.aliyun.oss.model.CompleteMultipartUploadResult; import com.aliyun.oss.model.InitiateMultipartUploadRequest; import com.aliyun.oss.model.InitiateMultipartUploadResult; import com.aliyun.oss.model.PartETag; import com.aliyun.oss.model.UploadPartRequest; import com.aliyun.oss.model.UploadPartResult; public class Demo { public static void main(String[] args) throws Exception { // Pada contoh ini, titik akhir wilayah China (Hangzhou) digunakan. Tentukan titik akhir aktual Anda. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com"; // Peroleh kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Tentukan nama bucket. Contoh: examplebucket. String bucketName = "examplebucket"; // Tentukan path lengkap objek. Jangan sertakan nama bucket dalam path lengkap. String objectName = "exampledir/object"; // Tentukan path file lokal yang ingin Anda unggah. String localFile = "D:\\localpath\\examplefile.txt"; // Tentukan wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur wilayah menjadi cn-hangzhou. String region = "cn-hangzhou"; // Buat instans OSSClient. // Panggil metode shutdown untuk melepaskan sumber daya saat OSSClient tidak lagi digunakan. ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); // Buat objek InitiateMultipartUploadRequest. InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName); // Opsional. Tentukan kelas penyimpanan. // ObjectMetadata metadata = new ObjectMetadata(); // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString()); // request.setObjectMetadata(metadata); // Mulai tugas unggah multi-bagian. InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request); // Peroleh ID unggah. ID unggah secara unik mengidentifikasi tugas unggah multi-bagian. Anda dapat menggunakan ID unggah untuk memulai permintaan terkait seperti membatalkan dan mengkueri tugas unggah multi-bagian. String uploadId = upresult.getUploadId(); // partETags adalah kumpulan PartETags. PartETag suatu bagian terdiri dari nomor bagian dan nilai ETag bagian tersebut. List<PartETag> partETags = new ArrayList<PartETag>(); // Hitung jumlah total bagian yang akan diunggah. final long partSize = 1 * 1024 * 1024L; // 1MB final File sampleFile = new File(localFile); long fileLength = sampleFile.length(); int partCount = (int) (fileLength / partSize); if (fileLength % partSize != 0) { partCount++; } // Unggah semua bagian. for (int i = 0; i < partCount; i++) { long startPos = i * partSize; long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize; InputStream instream = new FileInputStream(sampleFile); InputStream instream1 = new FileInputStream(sampleFile); // Lewati bagian yang telah diunggah. instream.skip(startPos); instream1.skip(startPos); String md5; if(i==partCount-1){ // Ukuran bagian terakhir belum tentu sama dengan ukuran bagian yang ditentukan. md5 = md5(instream1,fileLength - startPos); }else{ md5 = md5(instream1,partSize); } // instream1.skip(n) UploadPartRequest uploadPartRequest = new UploadPartRequest(); uploadPartRequest.setBucketName(bucketName); uploadPartRequest.setKey(objectName); uploadPartRequest.setUploadId(uploadId); uploadPartRequest.setInputStream(instream); uploadPartRequest.setMd5Digest(md5); // Tentukan ukuran bagian. Setiap bagian kecuali bagian terakhir harus sama dengan atau lebih besar dari 100 KB. uploadPartRequest.setPartSize(curPartSize); // Konfigurasikan nomor bagian. Setiap bagian dikonfigurasi dengan nomor bagian. Nilainya berkisar dari 1 hingga 10000. Jika Anda mengonfigurasi nomor di luar rentang tersebut, OSS mengembalikan kode kesalahan InvalidArgument. uploadPartRequest.setPartNumber( i + 1); // Bagian belum tentu diunggah secara berurutan dan dapat diunggah dari client OSS yang berbeda. OSS mengurutkan bagian berdasarkan nomor bagian dan menggabungkan bagian menjadi objek lengkap. UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest); // System.out.println("server md5" +uploadPartResult.getETag()); // Setiap kali bagian diunggah, OSS mengembalikan hasil yang berisi PartETag. PartETag disimpan di partETags. partETags.add(uploadPartResult.getPartETag()); } // Buat objek CompleteMultipartUploadRequest. // Saat Anda memanggil operasi CompleteMultipartUpload, Anda harus menyediakan semua PartETags yang valid. Setelah OSS menerima partETags, OSS memverifikasi semua bagian satu per satu. Setelah verifikasi bagian berhasil, OSS menggabungkan bagian-bagian tersebut menjadi objek lengkap. CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags); // Opsional. Atur daftar kontrol akses (ACL) objek. // completeMultipartUploadRequest.setObjectACL(CannedAccessControlList.PublicRead); // Selesaikan tugas unggah multi-bagian. CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest); // Tutup OSSClient Anda. ossClient.shutdown(); } public static String md5(InputStream in , long length1) throws Exception{ byte[] bytes = new byte[(int) length1]; long length_tmp = length1; int readSize = in.read(bytes, (int) 0, (int) length_tmp); return BinaryUtil.toBase64String(BinaryUtil.calculateMd5(bytes)); } }
Verifikasi CRC-64
Verifikasi CRC-64 diaktifkan secara default untuk operasi unggah, unduh, dan penyalinan objek.
-
CRC-64 berlaku untuk PutObject, GetObject, AppendObject, dan UploadPart. Fitur ini diaktifkan secara default. Jika checksum CRC-64 sisi klien berbeda dari checksum sisi server, kesalahan InconsistentException akan dilemparkan.
-
CRC-64 tidak didukung untuk unduhan rentang.
-
CRC-64 meningkatkan penggunaan CPU dan memperlambat proses unggah serta unduh.
-
CRC-64 untuk unduhan objek
Lakukan verifikasi CRC-64 selama unduhan objek:
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.common.comm.SignVersion; import com.aliyun.oss.common.utils.IOUtils; import com.aliyun.oss.internal.OSSHeaders; import com.aliyun.oss.internal.OSSUtils; import com.aliyun.oss.model.GetObjectRequest; import com.aliyun.oss.model.OSSObject; import java.io.BufferedReader; import java.io.InputStreamReader; public class Demo { public static void main(String[] args) throws Throwable { // Pada contoh ini, titik akhir wilayah China (Hangzhou) digunakan. Tentukan titik akhir aktual Anda. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // Peroleh kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Tentukan nama bucket. Contoh: examplebucket. String bucketName = "examplebucket"; // Tentukan path lengkap objek. Jangan sertakan nama bucket dalam path lengkap. String objectName = "exampledir/object"; // Tentukan wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur wilayah menjadi cn-hangzhou. String region = "cn-hangzhou"; // Buat instans OSSClient. // Panggil metode shutdown untuk melepaskan sumber daya saat OSSClient tidak lagi digunakan. ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); try { // Unduh objek dalam mode streaming. GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, objectName); OSSObject ossObject = ossClient.getObject(bucketName, objectName); // Baca objek dari aliran untuk memperoleh clientCRC. System.out.println("Konten objek:"); BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent())); while (true) { String line = reader.readLine(); if (line == null) break; System.out.println("\n" + line); } // Anda harus menutup aliran yang diperoleh setelah objek dibaca. Jika tidak, kebocoran koneksi dapat terjadi. Akibatnya, tidak ada koneksi yang tersedia dan terjadi pengecualian. reader.close(); // Periksa apakah CRC-64 diaktifkan di sisi client. Secara default, CRC-64 diaktifkan di sisi client. Boolean isCrcCheckEnabled = ((OSSClient)ossClient).getClientConfiguration().isCrcCheckEnabled(); // Periksa apakah permintaan unduh merupakan permintaan unduhan rentang. Verifikasi CRC-64 tidak didukung untuk unduhan rentang. Boolean isRangGetRequest = getObjectRequest.getHeaders().get(OSSHeaders.RANGE) != null; // Periksa apakah nilai CRC-64 dalam hasil yang dikembalikan sama dengan nilai objek yang diunduh. if (isCrcCheckEnabled && !isRangGetRequest) { Long clientCRC = IOUtils.getCRCValue(ossObject.getObjectContent()); OSSUtils.checkChecksum(clientCRC, ossObject.getServerCRC(), ossObject.getRequestId()); } } catch (OSSException oe) { System.out.println("Terjadi OSSException, yang berarti permintaan Anda sampai ke OSS, " + "tetapi ditolak dengan tanggapan kesalahan karena suatu alasan."); System.out.println("Pesan Kesalahan:" + oe.getErrorMessage()); System.out.println("Kode Kesalahan:" + oe.getErrorCode()); System.out.println("ID Permintaan:" + oe.getRequestId()); System.out.println("Host ID:" + oe.getHostId()); } catch (ClientException ce) { System.out.println("Terjadi ClientException, yang berarti client mengalami " + "masalah internal serius saat mencoba berkomunikasi dengan OSS, " + "seperti tidak dapat mengakses jaringan."); System.out.println("Pesan Kesalahan:" + ce.getMessage()); } finally { if (ossClient != null) { ossClient.shutdown(); } } } } -
CRC-64 untuk unggah append
Lakukan verifikasi CRC-64 selama unggah append:
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.common.comm.SignVersion; import com.aliyun.oss.model.*; import java.io.ByteArrayInputStream; public class Demo { public static void main(String[] args) throws Exception { // Pada contoh ini, titik akhir wilayah China (Hangzhou) digunakan. Tentukan titik akhir aktual Anda. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // Peroleh kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Tentukan nama bucket. Contoh: examplebucket. String bucketName = "examplebucket"; // Tentukan path lengkap objek. Contoh: exampleobject.txt. Jangan sertakan nama bucket dalam path lengkap. String objectName = "exampleobject.txt"; // Masukkan konten unggah append pertama, misalnya Hello. String firstAppendContent = "Hello"; // Masukkan konten unggah append kedua, misalnya World. String secondAppendContent = "World"; // Tentukan wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur wilayah menjadi cn-hangzhou. String region = "cn-hangzhou"; // Buat instans OSSClient. // Panggil metode shutdown untuk melepaskan sumber daya saat OSSClient tidak lagi digunakan. ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); try { // Lakukan operasi append pertama. AppendObjectRequest appendObjectRequest = new AppendObjectRequest(bucketName, objectName, new ByteArrayInputStream(firstAppendContent.getBytes())); appendObjectRequest.setPosition(0L); // Atur nilai CRC-64 awal. OSS SDK for Java secara default melakukan CRC-64 pada konten yang diunggah. appendObjectRequest.setInitCRC(0L); AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest); // Lakukan operasi unggah append kedua. appendObjectRequest = new AppendObjectRequest(bucketName, objectName, new ByteArrayInputStream(secondAppendContent.getBytes())); appendObjectRequest.setPosition(appendObjectResult.getNextPosition()); // Atur nilai CRC-64 ke nilai objek yang diunggah. OSS SDK for Java secara default melakukan CRC-64 pada konten yang diunggah. appendObjectRequest.setInitCRC(appendObjectResult.getClientCRC()); ossClient.appendObject(appendObjectRequest); } catch (OSSException oe) { System.out.println("Terjadi OSSException, yang berarti permintaan Anda sampai ke OSS, " + "tetapi ditolak dengan tanggapan kesalahan karena suatu alasan."); System.out.println("Pesan Kesalahan:" + oe.getErrorMessage()); System.out.println("Kode Kesalahan:" + oe.getErrorCode()); System.out.println("ID Permintaan:" + oe.getRequestId()); System.out.println("Host ID:" + oe.getHostId()); } catch (ClientException ce) { System.out.println("Terjadi ClientException, yang berarti client mengalami " + "masalah internal serius saat mencoba berkomunikasi dengan OSS, " + "seperti tidak dapat mengakses jaringan."); System.out.println("Pesan Kesalahan:" + ce.getMessage()); } finally { if (ossClient != null) { ossClient.shutdown(); } } } }
Referensi
Kode contoh lengkap untuk verifikasi MD5 dan CRC-64 tersedia di GitHub.