העלאות מרובות חלקים ב-API ל-XML

בדף הזה נסביר על העלאות מרובות חלקים באמצעות API בפורמט XML, ב-Cloud Storage. בשיטת ההעלאה הזו מעלים קבצים בחלקים, ואז מרכיבים אותם לאובייקט יחיד באמצעות בקשה סופית. העלאות מרובות חלקים באמצעות API בפורמט XML תואמות להעלאות מרובות חלקים ב-Amazon S3.

סקירה כללית

העלאה מרובת חלקים באמצעות API בפורמט XML מאפשרת להעלות נתונים במספר חלקים ואז להרכיב אותם לאובייקט סופי. להתנהגות הזו יש מספר יתרונות, במיוחד כשמדובר בקבצים גדולים:

  • אפשר להעלות חלקים בו-זמנית, וכך לקצר את הזמן הדרוש להעלאת כל הנתונים.

  • אם אחת מפעולות ההעלאה נכשלת, צריך להעלות מחדש רק חלק מהאובייקט הכולל, ולא להפעיל מחדש את כל ההעלאה.

  • גודל הקובץ הכולל לא מצוין מראש, כך שאפשר להשתמש בהעלאות מרובות חלקים באמצעות API בפורמט XML לצורך העלאות בסטרימינג או לצורך דחיסת נתונים בזמן ההעלאה.

העלאה מרובת חלקים באמצעות API בפורמט XML כוללת שלושה שלבים:

  1. התחלת ההעלאה באמצעות בקשת POST, הכוללת ציון של כל המטא-נתונים שצריכים להיות לאובייקט השלם. התשובה תחזיר UploadId שבו משתמשים בכל הבקשות הבאות הקשורות להעלאה.

  2. העלאת הנתונים באמצעות בקשת PUT אחת או יותר.

  3. השלמת ההעלאה באמצעות בקשת POST. הבקשה הזו מחליפה כל אובייקט קיים בקטגוריה שיש לו את אותו השם.

אין הגבלה על משך הזמן שבו העלאה מרובת חלקים והחלקים שלה שהועלו יכולים להישאר לא גמורים או ללא פעילות בקטגוריה.

  • כדי למנוע הצטברות של חלקים שנזנחו מהעלאות מרובות חלקים, אפשר להשתמש בניהול מחזור חיים של אובייקטים כדי להסיר באופן אוטומטי העלאות מרובות חלקים כשהן מגיעות לגיל מסוים.
  • לתשומת ליבכם

    המגבלות הבאות חלות על שימוש בהעלאות מרובות חלקים באמצעות API בפורמט XML:

    • יש מגבלות על הגודל המינימלי של חלק, על הגודל המקסימלי של חלק ועל מספר החלקים שמשמשים להרכבת ההעלאה המלאה.
    • הבקשות לא תומכות בתנאים מוקדמים.
    • לא קיימים גיבובים של MD5 בשביל אובייקטים שהועלו בשיטה הזו.
    • שיטת ההעלאה הזו לא אפשרית במסוף או ב-Google Cloud CLI. Cloud de Confiance

    כשעובדים עם העלאות מרובות חלקים באמצעות API בפורמט XML, חשוב לזכור את הדברים הבאים:

    • להעלאות מרובות חלקים באמצעות API בפורמט XML יש הרשאות IAM ספציפיות. אם אתם משתמשים בתפקידי IAM בהתאמה אישית, אתם צריכים לוודא שיש לתפקידים האלה את ההרשאות שאתם צריכים.

    • למרות שאפשר להתחיל העלאה ולהעלות חלקים, הבקשה להשלמת ההעלאה נכשלת אם היא מחליפה אובייקט שנמצא בהחזקה או בתקופת שמירה שטרם התמלאה.

    • אפשר להציג העלאות פעילות בקטגוריה, אבל רק העלאה שהושלמה תופיע ברשימה הרגילה של האובייקטים בקטגוריה.

    איך ספריות לקוח משתמשות בהעלאות מרובות חלקים באמצעות API בפורמט XML

    בקטע הזה מוסבר איך לבצע העלאות מרובות חלקים באמצעות API בפורמט XML, באמצעות ספריות לקוח שתומכות בכך.

    ספריות לקוח

    Java

    למידע נוסף, קראו את מאמרי העזרה של Cloud Storage Java API.

    כדי לבצע אימות ב-Cloud Storage, אתם צריכים להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לספריות לקוח.

    לפני שמריצים דוגמאות קוד, צריך להגדיר את משתנה הסביבה GOOGLE_CLOUD_UNIVERSE_DOMAIN לערך s3nsapis.fr.

    הדוגמה הבאה מפעילה העלאה מרובת חלקים:

    
    import com.google.cloud.storage.HttpStorageOptions;
    import com.google.cloud.storage.MultipartUploadClient;
    import com.google.cloud.storage.MultipartUploadSettings;
    import com.google.cloud.storage.multipartupload.model.CreateMultipartUploadRequest;
    import com.google.cloud.storage.multipartupload.model.CreateMultipartUploadResponse;
    import java.util.HashMap;
    import java.util.Map;
    
    public class CreateMultipartUpload {
      public static void createMultipartUpload(String projectId, String bucketName, String objectName) {
        // The ID of your GCP project
        // String projectId = "your-project-id";
    
        // The ID of your GCS bucket
        // String sourceBucketName = "your-unique-bucket-name";
    
        // The ID of your GCS object
        // String sourceObjectName = "your-object-name";
    
        HttpStorageOptions storageOptions =
            HttpStorageOptions.newBuilder().setProjectId(projectId).build();
        MultipartUploadSettings mpuSettings = MultipartUploadSettings.of(storageOptions);
        MultipartUploadClient mpuClient = MultipartUploadClient.create(mpuSettings);
    
        System.out.println("Initiating multipart upload for " + objectName);
    
        Map<String, String> metadata = new HashMap<>();
        metadata.put("key1", "value1");
        String contentType = "text/plain";
        CreateMultipartUploadRequest createRequest =
            CreateMultipartUploadRequest.builder()
                .bucket(bucketName)
                .key(objectName)
                .metadata(metadata)
                .contentType(contentType)
                .build();
    
        CreateMultipartUploadResponse createResponse = mpuClient.createMultipartUpload(createRequest);
        String uploadId = createResponse.uploadId();
        System.out.println("Upload ID: " + uploadId);
      }
    }

    הדוגמה הבאה מעלה חלק ספציפי של אובייקט:

    
    import com.google.cloud.storage.HttpStorageOptions;
    import com.google.cloud.storage.MultipartUploadClient;
    import com.google.cloud.storage.MultipartUploadSettings;
    import com.google.cloud.storage.RequestBody;
    import com.google.cloud.storage.multipartupload.model.UploadPartRequest;
    import com.google.cloud.storage.multipartupload.model.UploadPartResponse;
    import java.io.IOException;
    import java.nio.ByteBuffer;
    import java.util.Random;
    
    public class UploadPart {
      public static void uploadPart(
          String projectId, String bucketName, String objectName, String uploadId, int partNumber)
          throws IOException {
        // The ID of your GCP project
        // String projectId = "your-project-id";
    
        // The ID of your GCS bucket
        // String bucketName = "your-unique-bucket-name";
    
        // The ID of your GCS object
        // String objectName = "your-object-name";
    
        // The ID of the multipart upload
        // String uploadId = "your-upload-id";
    
        // The part number of the part being uploaded
        // int partNumber = 1;
    
        HttpStorageOptions storageOptions =
            HttpStorageOptions.newBuilder().setProjectId(projectId).build();
        MultipartUploadSettings mpuSettings = MultipartUploadSettings.of(storageOptions);
        MultipartUploadClient mpuClient = MultipartUploadClient.create(mpuSettings);
    
        // The minimum part size for a multipart upload is 5 MiB, except for the last part.
        byte[] bytes = new byte[5 * 1024 * 1024];
        new Random().nextBytes(bytes);
        RequestBody requestBody = RequestBody.of(ByteBuffer.wrap(bytes));
    
        System.out.println("Uploading part " + partNumber);
        UploadPartRequest uploadPartRequest =
            UploadPartRequest.builder()
                .bucket(bucketName)
                .key(objectName)
                .partNumber(partNumber)
                .uploadId(uploadId)
                .build();
    
        UploadPartResponse uploadPartResponse = mpuClient.uploadPart(uploadPartRequest, requestBody);
    
        System.out.println("Part " + partNumber + " uploaded with ETag: " + uploadPartResponse.eTag());
      }
    }

    בדוגמה הבאה מוצגת רשימה של חלקי אובייקט:

    
    import com.google.cloud.storage.HttpStorageOptions;
    import com.google.cloud.storage.MultipartUploadClient;
    import com.google.cloud.storage.MultipartUploadSettings;
    import com.google.cloud.storage.multipartupload.model.ListPartsRequest;
    import com.google.cloud.storage.multipartupload.model.ListPartsResponse;
    import com.google.cloud.storage.multipartupload.model.Part;
    
    public class ListParts {
      public static void listParts(
          String projectId, String bucketName, String objectName, String uploadId) {
        // The ID of your GCP project
        // String projectId = "your-project-id";
    
        // The ID of your GCS bucket
        // String bucketName = "your-unique-bucket-name";
    
        // The ID of your GCS object
        // String objectName = "your-object-name";
    
        // The ID of the multipart upload
        // String uploadId = "your-upload-id";
    
        HttpStorageOptions storageOptions =
            HttpStorageOptions.newBuilder().setProjectId(projectId).build();
        MultipartUploadSettings mpuSettings = MultipartUploadSettings.of(storageOptions);
        MultipartUploadClient mpuClient = MultipartUploadClient.create(mpuSettings);
    
        System.out.println("Listing parts for upload ID: " + uploadId);
    
        ListPartsRequest listPartsRequest =
            ListPartsRequest.builder().bucket(bucketName).key(objectName).uploadId(uploadId).build();
    
        ListPartsResponse listPartsResponse = mpuClient.listParts(listPartsRequest);
    
        if (listPartsResponse.parts() == null || listPartsResponse.parts().isEmpty()) {
          System.out.println("No parts have been uploaded yet.");
          return;
        }
    
        System.out.println("Uploaded Parts:");
        for (Part part : listPartsResponse.parts()) {
          System.out.println("  - Part Number: " + part.partNumber());
          System.out.println("    ETag: " + part.eTag());
          System.out.println("    Size: " + part.size() + " bytes");
          System.out.println("    Last Modified: " + part.lastModified());
        }
      }
    }

    הדוגמה הבאה משלימה העלאה מרובת חלקים:

    
    import com.google.cloud.storage.HttpStorageOptions;
    import com.google.cloud.storage.MultipartUploadClient;
    import com.google.cloud.storage.MultipartUploadSettings;
    import com.google.cloud.storage.multipartupload.model.CompleteMultipartUploadRequest;
    import com.google.cloud.storage.multipartupload.model.CompleteMultipartUploadResponse;
    import com.google.cloud.storage.multipartupload.model.CompletedMultipartUpload;
    import com.google.cloud.storage.multipartupload.model.CompletedPart;
    import java.util.List;
    
    public class CompleteMultipartUpload {
      public static void completeMultipartUpload(
          String projectId,
          String bucketName,
          String objectName,
          String uploadId,
          List<CompletedPart> completedParts) {
    
        // The ID of your GCP project
        // String projectId = "your-project-id";
    
        // The ID of your GCS bucket
        // String bucketName = "your-unique-bucket-name";
    
        // The ID of your GCS object
        // String objectName = "your-object-name";
    
        // The ID of the multipart upload
        // String uploadId = "your-upload-id";
    
        // The list of completed parts from the UploadPart responses.
        // List<CompletedPart> completedParts = ...;
    
        HttpStorageOptions storageOptions =
            HttpStorageOptions.newBuilder().setProjectId(projectId).build();
        MultipartUploadSettings mpuSettings = MultipartUploadSettings.of(storageOptions);
        MultipartUploadClient mpuClient = MultipartUploadClient.create(mpuSettings);
    
        System.out.println("Completing multipart upload for " + objectName);
    
        CompletedMultipartUpload completedMultipartUpload =
            CompletedMultipartUpload.builder().parts(completedParts).build();
    
        CompleteMultipartUploadRequest completeRequest =
            CompleteMultipartUploadRequest.builder()
                .bucket(bucketName)
                .key(objectName)
                .uploadId(uploadId)
                .multipartUpload(completedMultipartUpload)
                .build();
    
        CompleteMultipartUploadResponse completeResponse =
            mpuClient.completeMultipartUpload(completeRequest);
    
        System.out.println(
            "Upload complete for "
                + completeResponse.key()
                + " in bucket "
                + completeResponse.bucket());
        System.out.println("Final ETag: " + completeResponse.etag());
      }
    }

    Node.js

    למידע נוסף, קראו את מאמרי העזרה של Cloud Storage Node.js API.

    כדי לבצע אימות ב-Cloud Storage, אתם צריכים להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לספריות לקוח.

    לפני שמריצים דוגמאות קוד, צריך להגדיר את משתנה הסביבה GOOGLE_CLOUD_UNIVERSE_DOMAIN לערך s3nsapis.fr.

    אפשר לבצע העלאות מרובות חלקים באמצעות API בפורמט XML באמצעות ה-method‏ uploadFileInChunks. לדוגמה:

    /**
     * TODO(developer): Uncomment the following lines before running the sample.
     */
    // The ID of your GCS bucket
    // const bucketName = 'your-unique-bucket-name';
    
    // The path of file to upload
    // const filePath = 'path/to/your/file';
    
    // The size of each chunk to be uploaded
    // const chunkSize = 32 * 1024 * 1024;
    
    // Imports the Google Cloud client library
    const {Storage, TransferManager} = require('@google-cloud/storage');
    
    // Creates a client
    const storage = new Storage();
    
    // Creates a transfer manager client
    const transferManager = new TransferManager(storage.bucket(bucketName));
    
    async function uploadFileInChunksWithTransferManager() {
      // Uploads the files
      await transferManager.uploadFileInChunks(filePath, {
        chunkSizeBytes: chunkSize,
      });
    
      console.log(`${filePath} uploaded to ${bucketName}.`);
    }
    
    uploadFileInChunksWithTransferManager().catch(console.error);

    Python

    למידע נוסף, קראו את מאמרי העזרה של Cloud Storage Python API.

    כדי לבצע אימות ב-Cloud Storage, אתם צריכים להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לספריות לקוח.

    לפני שמריצים דוגמאות קוד, צריך להגדיר את משתנה הסביבה GOOGLE_CLOUD_UNIVERSE_DOMAIN לערך s3nsapis.fr.

    אפשר לבצע העלאות מרובות חלקים באמצעות API בפורמט XML באמצעות ה-method‏ upload_chunks_concurrently. לדוגמה:

    def upload_chunks_concurrently(
        bucket_name,
        source_filename,
        destination_blob_name,
        chunk_size=32 * 1024 * 1024,
        workers=8,
    ):
        """Upload a single file, in chunks, concurrently in a process pool."""
        # The ID of your GCS bucket
        # bucket_name = "your-bucket-name"
    
        # The path to your file to upload
        # source_filename = "local/path/to/file"
    
        # The ID of your GCS object
        # destination_blob_name = "storage-object-name"
    
        # The size of each chunk. The performance impact of this value depends on
        # the use case. The remote service has a minimum of 5 MiB and a maximum of
        # 5 GiB.
        # chunk_size = 32 * 1024 * 1024 (32 MiB)
    
        # The maximum number of processes to use for the operation. The performance
        # impact of this value depends on the use case. Each additional process
        # occupies some CPU and memory resources until finished. Threads can be used
        # instead of processes by passing `worker_type=transfer_manager.THREAD`.
        # workers=8
    
        from google.cloud.storage import Client, transfer_manager
    
        storage_client = Client()
        bucket = storage_client.bucket(bucket_name)
        blob = bucket.blob(destination_blob_name)
    
        transfer_manager.upload_chunks_concurrently(
            source_filename, blob, chunk_size=chunk_size, max_workers=workers
        )
    
        print(f"File {source_filename} uploaded to {destination_blob_name}.")
    
    
    if __name__ == "__main__":
        argparse = argparse.ArgumentParser(
            description="Upload a file to GCS in chunks concurrently."
        )
        argparse.add_argument(
            "--bucket_name", help="The name of the GCS bucket to upload to."
        )
        argparse.add_argument(
            "--source_filename", help="The local path to the file to upload."
        )
        argparse.add_argument(
            "--destination_blob_name", help="The name of the object in GCS."
        )
        argparse.add_argument(
            "--chunk_size",
            type=int,
            default=32 * 1024 * 1024,
            help="The size of each chunk in bytes (default: 32 MiB). The remote\
                  service has a minimum of 5 MiB and a maximum of 5 GiB",
        )
        argparse.add_argument(
            "--workers",
            type=int,
            default=8,
            help="The number of worker processes to use (default: 8).",
        )
        args = argparse.parse_args()
        upload_chunks_concurrently(
            args.bucket_name,
            args.source_filename,
            args.destination_blob_name,
            args.chunk_size,
            args.workers,
        )
    
    

    המאמרים הבאים