All Products
Search
Document Center

Object Storage Service:Mengunduh objek ke file lokal (Java SDK V1)

Last Updated:Nov 28, 2025

Topik ini menjelaskan cara mengunduh objek dari bucket Object Storage Service (OSS) ke file lokal.

Catatan

  • Pada topik ini, digunakan 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 Wilayah dan titik akhir.

  • Kredensial akses pada topik ini diperoleh dari variabel lingkungan. Untuk informasi selengkapnya tentang cara mengonfigurasi kredensial akses, lihat Konfigurasi kredensial akses.

  • Pada topik ini, instans OSSClient dibuat menggunakan titik akhir OSS. Jika Anda ingin membuat instans OSSClient dengan nama domain kustom atau Security Token Service (STS), lihat Contoh konfigurasi untuk skenario umum.

Izin

Secara default, Akun Alibaba Cloud memiliki izin penuh. Pengguna RAM atau Peran RAM di bawah Akun Alibaba Cloud tidak memiliki izin apa pun secara default. Akun Alibaba Cloud atau administrator akun harus memberikan izin operasi melalui Kebijakan RAM atau Kebijakan bucket.

API

Tindakan

Definisi

GetObject

oss:GetObject

Mengunduh objek.

oss:GetObjectVersion

Saat mengunduh objek, jika Anda menentukan versi objek melalui versionId, izin ini diperlukan.

kms:Decrypt

Saat mengunduh objek, jika metadata objek berisi X-Oss-Server-Side-Encryption: KMS, izin ini diperlukan.

Mengunduh satu objek ke file lokal

Kode berikut menunjukkan cara mengunduh objek exampleobject.txt dari folder testfolder di bucket examplebucket dan menyimpannya sebagai examplefile.txt ke path lokal D:\localpath.

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.GetObjectRequest;
import java.io.File;

public class Demo {

    public static void main(String[] args) throws Exception {
        // Tetapkan Endpoint. Gunakan wilayah China (Hangzhou) sebagai contoh. Atur Endpoint sesuai wilayah sebenarnya.
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // Dapatkan 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. Contoh: testfolder/exampleobject.txt.
        String objectName = "testfolder/exampleobject.txt";
        // Tentukan path lengkap tujuan pengunduhan objek.
        String pathName = "D:\\localpath\\examplefile.txt";
        // Tentukan wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur Region ke cn-hangzhou.
        String region = "cn-hangzhou";

        // Buat instans OSSClient.
        // Setelah instans OSSClient tidak digunakan lagi, panggil metode shutdown untuk melepaskan sumber daya.
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);        
        OSS ossClient = OSSClientBuilder.create()
        .endpoint(endpoint)
        .credentialsProvider(credentialsProvider)
        .clientConfiguration(clientBuilderConfiguration)
        .region(region)               
        .build();

        try {
            // Unduh objek ke file lokal dan simpan ke path lokal yang ditentukan. Jika file lokal yang ditentukan sudah ada, file tersebut akan ditimpa. Jika belum ada, file tersebut akan dibuat.
            // Jika Anda tidak menentukan path lokal, objek yang diunduh akan disimpan ke path lokal yang sesuai dengan proyek program contoh secara default.
            ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(pathName));
        } catch (OSSException oe) {
            System.out.println("Terjadi OSSException, yang berarti permintaan Anda sampai ke OSS, "
                    + "tetapi ditolak dengan tanggapan 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 klien mengalami "
                    + "masalah internal serius saat mencoba berkomunikasi dengan OSS, "
                    + "seperti tidak dapat mengakses jaringan.");
            System.out.println("Pesan Error:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}   

Mengunduh beberapa objek ke path lokal

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.File;
import java.io.IOException;
import java.util.List;

public class BatchDownloadObject {
    public static void main(String[] args) throws Exception {
        // Tetapkan Endpoint. Gunakan wilayah China (Hangzhou) sebagai contoh. Atur Endpoint sesuai wilayah sebenarnya.
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // Dapatkan 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 = "examplebuckett";
        // Tentukan awalan folder yang akan diunduh. Contoh: "images/". Untuk mengunduh seluruh bucket, biarkan kosong.
        String folderPrefix = "";
        // Tentukan folder unduhan lokal.
        String localDownloadPath = "./batch_downloads/";
        // Tentukan wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur Region ke cn-hangzhou.
        String region = "cn-hangzhou";

        // Buat instans OSSClient.
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);

        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();

        try {
            // Pastikan folder unduhan lokal tersedia.
            createDirectoryIfNotExists(localDownloadPath);

            // Unduh objek secara batch.
            batchDownloadObjects(ossClient, bucketName, folderPrefix, localDownloadPath);

        } catch (OSSException oe) {
            System.out.println("Terjadi OSSException, yang berarti permintaan Anda sampai ke OSS, "
                    + "tetapi ditolak dengan tanggapan 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 klien mengalami "
                    + "masalah internal serius saat mencoba berkomunikasi dengan OSS, "
                    + "seperti tidak dapat mengakses jaringan.");
            System.out.println("Pesan Error:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * Mengunduh objek dari OSS ke path lokal secara batch.
     * @param ossClient Klien OSS.
     * @param bucketName Nama bucket.
     * @param folderPrefix Awalan folder.
     * @param localDownloadPath Path unduhan lokal.
     */
    public static void batchDownloadObjects(OSS ossClient, String bucketName, String folderPrefix, String localDownloadPath) {
        String nextMarker = null;
        ObjectListing objectListing;
        int downloadCount = 0;
        long totalSize = 0;
        int failedCount = 0;

        System.out.println("Memulai pengunduhan batch...");
        System.out.println("Path sumber: " + bucketName + "/" + folderPrefix);
        System.out.println("Path lokal: " + localDownloadPath);
        System.out.println("----------------------------------------");

        long startTime = System.currentTimeMillis();

        do {
            // Daftar objek.
            ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName)
                    .withPrefix(folderPrefix)
                    .withMarker(nextMarker)
                    .withMaxKeys(1000); // Daftarkan maksimal 1.000 objek sekaligus.

            objectListing = ossClient.listObjects(listObjectsRequest);
            List<OSSObjectSummary> sums = objectListing.getObjectSummaries();

            for (OSSObjectSummary s : sums) {
                // Lewati folder (objek yang diakhiri dengan /).
                if (s.getKey().endsWith("/")) {
                    continue;
                }

                try {
                    // Bangun path file lokal.
                    String localFilePath = constructLocalFilePath(localDownloadPath, s.getKey(), folderPrefix);

                    // Buat folder induk file lokal.
                    File localFile = new File(localFilePath);
                    createDirectoryIfNotExists(localFile.getParent());

                    // Periksa apakah file sudah ada untuk menghindari pengunduhan berulang.
                    if (localFile.exists() && localFile.length() == s.getSize()) {
                        System.out.println("File sudah ada. Lewati pengunduhan: " + s.getKey());
                        downloadCount++;
                        totalSize += s.getSize();
                        continue;
                    }

                    // Unduh objek.
                    System.out.println("Mengunduh: " + s.getKey() + " -> " + localFilePath);

                    // Gunakan file sementara untuk mencegah kerusakan file selama pengunduhan.
                    File tempFile = new File(localFilePath + ".tmp");
                    try {
                        ossClient.getObject(new GetObjectRequest(bucketName, s.getKey()), tempFile);

                        // Setelah pengunduhan selesai, ubah nama file sementara menjadi nama file akhir.
                        if (tempFile.renameTo(localFile)) {
                            downloadCount++;
                            totalSize += s.getSize();
                            System.out.println("Pengunduhan selesai: " + s.getKey() + " (Ukuran: " + formatFileSize(s.getSize()) + ")");
                        } else {
                            throw new IOException("Gagal mengubah nama file sementara: " + tempFile.getPath() + " -> " + localFile.getPath());
                        }
                    } finally {
                        // Bersihkan file sementara.
                        if (tempFile.exists()) {
                            tempFile.delete();
                        }
                    }

                } catch (Exception e) {
                    failedCount++;
                    System.err.println("Gagal mengunduh file: " + s.getKey() + ", Error: " + e.getMessage());
                    // Catat pesan error detail untuk debugging.
                    if (e instanceof OSSException) {
                        OSSException oe = (OSSException) e;
                        System.err.println("Kode Error OSS: " + oe.getErrorCode() + ", ID Permintaan: " + oe.getRequestId());
                    }
                }
            }

            nextMarker = objectListing.getNextMarker();
        } while (objectListing.isTruncated());

        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;

        System.out.println("----------------------------------------");
        System.out.println("Pengunduhan batch selesai!");
        System.out.println("Total jumlah file yang diunduh: " + downloadCount);
        System.out.println("Jumlah pengunduhan yang gagal: " + failedCount);
        System.out.println("Total ukuran unduhan: " + formatFileSize(totalSize));
        System.out.println("Total waktu yang berlalu: " + formatDuration(duration));
        System.out.println("Kecepatan unduh rata-rata: " + formatSpeed(totalSize, duration));
    }

    /**
     * Membangun path file lokal.
     * @param localDownloadPath Direktori root untuk unduhan lokal.
     * @param objectKey Kunci objek OSS.
     * @param folderPrefix Awalan folder.
     * @return Path lengkap file lokal.
     */
    private static String constructLocalFilePath(String localDownloadPath, String objectKey, String folderPrefix) {
        // Hapus awalan untuk mempertahankan struktur path relatif.
        String relativePath = objectKey;
        if (folderPrefix != null && !folderPrefix.isEmpty() && objectKey.startsWith(folderPrefix)) {
            relativePath = objectKey.substring(folderPrefix.length());
        }

        // Pastikan pemisah path benar.
        String normalizedPath = localDownloadPath.endsWith(File.separator) ?
                localDownloadPath : localDownloadPath + File.separator;

        return normalizedPath + relativePath.replace("/", File.separator);
    }

    /**
     * Membuat folder jika belum ada.
     * @param dirPath Path folder.
     */
    private static void createDirectoryIfNotExists(String dirPath) {
        if (dirPath == null || dirPath.isEmpty()) {
            return;
        }

        try {
            File dir = new File(dirPath);
            if (!dir.exists()) {
                boolean created = dir.mkdirs();
                if (created) {
                    System.out.println("Membuat folder: " + dirPath);
                } else if (!dir.exists()) {
                    throw new IOException("Gagal membuat folder: " + dirPath);
                }
            }
        } catch (Exception e) {
            System.err.println("Gagal membuat folder: " + dirPath + ", Error: " + e.getMessage());
            throw new RuntimeException("Gagal membuat folder", e);
        }
    }

    /**
     * Memformat ukuran file.
     * @param size Ukuran file dalam byte.
     * @return String ukuran file yang diformat.
     */
    private static String formatFileSize(long size) {
        if (size < 1024) {
            return size + " B";
        } else if (size < 1024 * 1024) {
            return String.format("%.2f KB", size / 1024.0);
        } else if (size < 1024 * 1024 * 1024) {
            return String.format("%.2f MB", size / (1024.0 * 1024.0));
        } else {
            return String.format("%.2f GB", size / (1024.0 * 1024.0 * 1024.0));
        }
    }

    /**
     * Memformat durasi.
     * @param duration Durasi dalam milidetik.
     * @return String durasi yang diformat.
     */
    private static String formatDuration(long duration) {
        long seconds = duration / 1000;
        long minutes = seconds / 60;
        long hours = minutes / 60;

        if (hours > 0) {
            return String.format("%d jam %d menit %d detik", hours, minutes % 60, seconds % 60);
        } else if (minutes > 0) {
            return String.format("%d menit %d detik", minutes, seconds % 60);
        } else {
            return String.format("%d detik", seconds);
        }
    }

    /**
     * Memformat kecepatan unduh.
     * @param totalBytes Total jumlah byte.
     * @param durationMs Durasi dalam milidetik.
     * @return String kecepatan yang diformat.
     */
    private static String formatSpeed(long totalBytes, long durationMs) {
        if (durationMs <= 0) {
            return "N/A";
        }

        double bytesPerSecond = (double) totalBytes / (durationMs / 1000.0);

        if (bytesPerSecond < 1024) {
            return String.format("%.2f B/dtk", bytesPerSecond);
        } else if (bytesPerSecond < 1024 * 1024) {
            return String.format("%.2f KB/dtk", bytesPerSecond / 1024.0);
        } else if (bytesPerSecond < 1024 * 1024 * 1024) {
            return String.format("%.2f MB/dtk", bytesPerSecond / (1024.0 * 1024.0));
        } else {
            return String.format("%.2f GB/dtk", bytesPerSecond / (1024.0 * 1024.0 * 1024.0));
        }
    }
}

Operasi API terkait

Jika program Anda memiliki persyaratan kustomisasi lanjutan, Anda dapat langsung mengirim permintaan REST API. Untuk mengirim permintaan REST API secara langsung, Anda harus menulis kode secara manual untuk menghitung signature. Untuk informasi selengkapnya, lihat GetObject.

Referensi

  • Untuk kode contoh lengkap mengenai pengunduhan objek ke file lokal, lihat GitHub.