OSS menyediakan MD5 dan Pemeriksaan redundansi siklik 64-bit (CRC-64) untuk validasi data guna memastikan integritas data saat Anda mengunggah, mengunduh, dan menyalin objek.
Catatan penggunaan
Topik ini menggunakan Titik akhir publik wilayah China (Hangzhou). Untuk mengakses OSS dari layanan Alibaba Cloud lainnya di wilayah yang sama, gunakan Titik akhir internal. Untuk detail wilayah dan titik akhir yang didukung, lihat Wilayah dan titik akhir.
Topik ini memperoleh kredensial akses dari Variabel lingkungan. Untuk informasi selengkapnya tentang cara mengonfigurasi kredensial akses, lihat Konfigurasi kredensial akses.
Topik ini membuat instans OSSClient menggunakan titik akhir OSS. Jika Anda ingin membuat instans OSSClient menggunakan nama domain kustom atau Security Token Service (STS), lihat Contoh konfigurasi untuk skenario umum.
Validasi MD5
Saat mengunggah file, Anda dapat mengatur header Content-MD5 untuk memastikan integritas data. OSS menghitung Hash MD5 dari konten yang diterima. Jika Hash MD5 yang dihitung oleh OSS tidak sesuai dengan nilai yang Anda berikan, OSS akan mengembalikan error InvalidDigest. Dalam hal ini, Anda harus mengunggah ulang file tersebut.
Validasi MD5 juga didukung untuk unggah multi-bagian. Pada unggah multi-bagian, validasi MD5 dilakukan pada setiap bagian. Untuk melakukannya, panggil metode setMd5Digest dalam UploadPartRequest untuk mengatur Hash MD5 dari bagian yang dihitung oleh klien.
Validasi MD5 didukung untuk operasi putObject, getObject, appendObject, postObject, unggah multi-bagian, dan uploadPart.
Lakukan validasi MD5 saat mengunggah file:
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 { // Contoh ini menggunakan titik akhir wilayah China (Hangzhou). Ganti nilai ini dengan titik akhir yang sebenarnya. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // Peroleh kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh ini, 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. Path lengkap tidak boleh mengandung nama bucket. String objectName = "exampledir/object"; // Tentukan wilayah tempat bucket berada. Contoh ini menggunakan cn-hangzhou untuk bucket di wilayah China (Hangzhou). String region = "cn-hangzhou"; // Buat instans OSSClient. // Saat instans OSSClient tidak lagi digunakan, panggil metode shutdown untuk melepas sumber daya. 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(); // Aktifkan validasi 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 berhasil mencapai OSS, " + "tetapi ditolak dengan respons error karena suatu alasan."); System.out.println("Pesan Error:" + oe.getErrorMessage()); System.out.println("Kode Error:" + 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, " + "misalnya tidak dapat mengakses jaringan."); System.out.println("Pesan Error:" + ce.getMessage()); } finally { if (ossClient != null) { ossClient.shutdown(); } } } }Lakukan validasi MD5 untuk 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 { // Contoh ini menggunakan titik akhir wilayah China (Hangzhou). Ganti nilai ini dengan titik akhir yang sebenarnya. String endpoint = "http://oss-cn-hangzhou.aliyuncs.com"; // Peroleh kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh ini, 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. Path lengkap tidak boleh mengandung nama bucket. String objectName = "exampledir/object"; // Path file lokal yang akan diunggah. String localFile = "D:\\localpath\\examplefile.txt"; // Tentukan wilayah tempat bucket berada. Contoh ini menggunakan cn-hangzhou untuk bucket di wilayah China (Hangzhou). String region = "cn-hangzhou"; // Buat instans OSSClient. // Saat instans OSSClient tidak lagi digunakan, panggil metode shutdown untuk melepas sumber daya. 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); // Untuk mengatur kelas penyimpanan saat menginisialisasi unggah multi-bagian, lihat kode contoh berikut. // ObjectMetadata metadata = new ObjectMetadata(); // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString()); // request.setObjectMetadata(metadata); // Inisialisasi unggah multi-bagian. InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request); // ID unggah dikembalikan. ID unggah secara unik mengidentifikasi event unggah multi-bagian. Anda dapat menggunakan ID unggah untuk melakukan operasi seperti membatalkan unggah multi-bagian dan mengkueri bagian-bagian. String uploadId = upresult.getUploadId(); // partETags adalah kumpulan objek PartETag. Objek PartETag terdiri dari ETag dan nomor bagian suatu bagian. List<PartETag> partETags = new ArrayList<PartETag>(); // Hitung jumlah bagian. final long partSize = 1 * 1024 * 1024L; // 1 MB final File sampleFile = new File(localFile); long fileLength = sampleFile.length(); int partCount = (int) (fileLength / partSize); if (fileLength % partSize != 0) { partCount++; } // Lakukan iterasi pada bagian-bagian dan unggah. 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-bagian yang telah diunggah. instream.skip(startPos); instream1.skip(startPos); String md5; if(i==partCount-1){ // Catatan: Untuk bagian terakhir, data dibaca hingga akhir file, bukan sebesar ukuran bagian. 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); // Tetapkan ukuran bagian. Ukuran minimum suatu bagian adalah 100 KB, kecuali untuk bagian terakhir. uploadPartRequest.setPartSize(curPartSize); // Tetapkan nomor bagian. Setiap bagian yang diunggah memiliki nomor bagian yang berkisar antara 1 hingga 10.000. Jika nomor bagian berada di luar rentang tersebut, OSS mengembalikan error InvalidArgument. uploadPartRequest.setPartNumber( i + 1); // Anda tidak perlu mengunggah bagian secara berurutan. Anda bahkan dapat mengunggah bagian dari client yang berbeda. OSS menggabungkan bagian-bagian tersebut menjadi file lengkap berdasarkan nomor bagiannya. UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest); // System.out.println("server md5" +uploadPartResult.getETag()); // Setelah setiap bagian diunggah, OSS mengembalikan hasil yang berisi PartETag. PartETag disimpan dalam partETags. partETags.add(uploadPartResult.getPartETag()); } // Buat objek CompleteMultipartUploadRequest. // Saat menyelesaikan unggah multi-bagian, Anda harus menyediakan semua partETags yang valid. Setelah OSS menerima partETags yang diajukan, OSS memverifikasi validitas setiap bagian. Setelah semua bagian diverifikasi, OSS menggabungkannya menjadi file lengkap. CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags); // Untuk mengatur izin akses pada file saat menyelesaikan unggah multi-bagian, lihat kode contoh berikut. // completeMultipartUploadRequest.setObjectACL(CannedAccessControlList.PublicRead); // Selesaikan unggahan. CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest); // Matikan OSSClient. 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)); } }
Validasi CRC-64
Secara default, validasi data CRC-64 diaktifkan untuk operasi unggah, unduh, dan salin file guna memastikan integritas data.
Operasi putObject, getObject, appendObject, dan uploadPart mendukung validasi CRC-64. Secara default, validasi CRC-64 diaktifkan untuk unggahan. Jika nilai CRC yang dihitung oleh klien berbeda dari nilai CRC yang dikembalikan oleh server, error InconsistentException akan dilemparkan.
Unduhan rentang tidak mendukung validasi CRC-64.
Validasi CRC-64 mengonsumsi sumber daya CPU dan dapat memengaruhi kecepatan unggah dan unduh.
Lakukan validasi CRC-64 saat mengunduh file:
Kode berikut menunjukkan cara menggunakan CRC-64 untuk memvalidasi integritas data saat mengunduh file:
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 { // Contoh ini menggunakan titik akhir wilayah China (Hangzhou). Ganti nilai ini dengan titik akhir yang sebenarnya. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // Peroleh kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh ini, 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. Path lengkap tidak boleh mengandung nama bucket. String objectName = "exampledir/object"; // Tentukan wilayah tempat bucket berada. Contoh ini menggunakan cn-hangzhou untuk bucket di wilayah China (Hangzhou). String region = "cn-hangzhou"; // Buat instans OSSClient. // Saat instans OSSClient tidak lagi digunakan, panggil metode shutdown untuk melepas sumber daya. ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); try { // Lakukan unduhan streaming. GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, objectName); OSSObject ossObject = ossClient.getObject(bucketName, objectName); // Baca konten file. Anda hanya dapat memperoleh clientCrc setelah membaca konten file. 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); } // Setelah data dibaca, Anda harus menutup stream. Jika tidak, kebocoran koneksi dapat terjadi. Hal ini menyebabkan program kehabisan koneksi yang tersedia dan berhenti bekerja. reader.close(); // Periksa apakah validasi CRC diaktifkan pada client. Secara default, fitur ini diaktifkan. Boolean isCrcCheckEnabled = ((OSSClient)ossClient).getClientConfiguration().isCrcCheckEnabled(); // Periksa apakah permintaan merupakan unduhan rentang. Unduhan rentang tidak mendukung validasi CRC. Boolean isRangGetRequest = getObjectRequest.getHeaders().get(OSSHeaders.RANGE) != null; // Validasi CRC. Anda hanya dapat memperoleh clientCRC setelah membaca konten file. 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 berhasil mencapai OSS, " + "tetapi ditolak dengan respons error karena suatu alasan."); System.out.println("Pesan Error:" + oe.getErrorMessage()); System.out.println("Kode Error:" + 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, " + "misalnya tidak dapat mengakses jaringan."); System.out.println("Pesan Error:" + ce.getMessage()); } finally { if (ossClient != null) { ossClient.shutdown(); } } } }Lakukan validasi CRC-64 untuk unggah append:
Kode berikut menunjukkan cara menggunakan CRC-64 untuk memvalidasi integritas data pada 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 { // Contoh ini menggunakan titik akhir wilayah China (Hangzhou). Ganti nilai ini dengan titik akhir yang sebenarnya. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // Peroleh kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh ini, 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, misalnya exampleobject.txt. Path lengkap tidak boleh mengandung nama bucket. String objectName = "exampleobject.txt"; // Tentukan konten untuk operasi append pertama. Contoh: Hello. String firstAppendContent = "Hello"; // Tentukan konten untuk operasi append kedua. Contoh: World. String secondAppendContent = "World"; // Tentukan wilayah tempat bucket berada. Contoh ini menggunakan cn-hangzhou untuk bucket di wilayah China (Hangzhou). String region = "cn-hangzhou"; // Buat instans OSSClient. // Saat instans OSSClient tidak lagi digunakan, panggil metode shutdown untuk melepas sumber daya. 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); // Inisialisasi CRC. Setelah diinisialisasi, SDK secara default melakukan validasi CRC pada hasil unggahan. appendObjectRequest.setInitCRC(0L); AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest); // Lakukan operasi append kedua. appendObjectRequest = new AppendObjectRequest(bucketName, objectName, new ByteArrayInputStream(secondAppendContent.getBytes())); appendObjectRequest.setPosition(appendObjectResult.getNextPosition()); // Tetapkan CRC awal ke CRC dari data yang telah diunggah. Setelah diinisialisasi, SDK secara default melakukan validasi CRC pada hasil unggahan. appendObjectRequest.setInitCRC(appendObjectResult.getClientCRC()); ossClient.appendObject(appendObjectRequest); } catch (OSSException oe) { System.out.println("Terjadi OSSException, yang berarti permintaan Anda berhasil mencapai OSS, " + "tetapi ditolak dengan respons error karena suatu alasan."); System.out.println("Pesan Error:" + oe.getErrorMessage()); System.out.println("Kode Error:" + 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, " + "misalnya tidak dapat mengakses jaringan."); System.out.println("Pesan Error:" + ce.getMessage()); } finally { if (ossClient != null) { ossClient.shutdown(); } } } }
Referensi
Untuk kode contoh lengkap mengenai validasi data, lihat contoh GitHub.