completeMultipartUpload - Completes a multipart upload by assembling previously uploaded parts.
(ctx context.Context, bucketName, objectName, uploadID string, complete completeMultipartUpload, opts PutObjectOptions, )
| 373 | |
| 374 | // completeMultipartUpload - Completes a multipart upload by assembling previously uploaded parts. |
| 375 | func (c *Client) completeMultipartUpload(ctx context.Context, bucketName, objectName, uploadID string, |
| 376 | complete completeMultipartUpload, opts PutObjectOptions, |
| 377 | ) (UploadInfo, error) { |
| 378 | // Input validation. |
| 379 | if err := s3utils.CheckValidBucketName(bucketName); err != nil { |
| 380 | return UploadInfo{}, err |
| 381 | } |
| 382 | if err := s3utils.CheckValidObjectName(objectName); err != nil { |
| 383 | return UploadInfo{}, err |
| 384 | } |
| 385 | |
| 386 | // Initialize url queries. |
| 387 | urlValues := make(url.Values) |
| 388 | urlValues.Set("uploadId", uploadID) |
| 389 | // Marshal complete multipart body. |
| 390 | completeMultipartUploadBytes, err := xml.Marshal(complete) |
| 391 | if err != nil { |
| 392 | return UploadInfo{}, err |
| 393 | } |
| 394 | |
| 395 | headers := opts.Header() |
| 396 | if s3utils.IsAmazonEndpoint(*c.endpointURL) { |
| 397 | headers.Del(encrypt.SseKmsKeyID) // Remove X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id not supported in CompleteMultipartUpload |
| 398 | headers.Del(encrypt.SseGenericHeader) // Remove X-Amz-Server-Side-Encryption not supported in CompleteMultipartUpload |
| 399 | headers.Del(encrypt.SseEncryptionContext) // Remove X-Amz-Server-Side-Encryption-Context not supported in CompleteMultipartUpload |
| 400 | } |
| 401 | |
| 402 | // Instantiate all the complete multipart buffer. |
| 403 | completeMultipartUploadBuffer := bytes.NewReader(completeMultipartUploadBytes) |
| 404 | reqMetadata := requestMetadata{ |
| 405 | bucketName: bucketName, |
| 406 | objectName: objectName, |
| 407 | queryValues: urlValues, |
| 408 | contentBody: completeMultipartUploadBuffer, |
| 409 | contentLength: int64(len(completeMultipartUploadBytes)), |
| 410 | contentSHA256Hex: sum256Hex(completeMultipartUploadBytes), |
| 411 | customHeader: headers, |
| 412 | expect200OKWithError: true, |
| 413 | } |
| 414 | |
| 415 | // Execute POST to complete multipart upload for an objectName. |
| 416 | resp, err := c.executeMethod(ctx, http.MethodPost, reqMetadata) |
| 417 | defer closeResponse(resp) |
| 418 | if err != nil { |
| 419 | return UploadInfo{}, err |
| 420 | } |
| 421 | if resp != nil { |
| 422 | if resp.StatusCode != http.StatusOK { |
| 423 | return UploadInfo{}, httpRespToErrorResponse(resp, bucketName, objectName) |
| 424 | } |
| 425 | } |
| 426 | |
| 427 | // Read resp.Body into a []bytes to parse for Error response inside the body |
| 428 | var b []byte |
| 429 | b, err = io.ReadAll(resp.Body) |
| 430 | if err != nil { |
| 431 | return UploadInfo{}, err |
| 432 | } |