| 510 | } |
| 511 | |
| 512 | bool S3InterfaceService::completeMultiPart(const S3Url &s3Url, const string &uploadId, |
| 513 | const vector<string> &etagArray) { |
| 514 | HTTPHeaders headers; |
| 515 | stringstream queryString; |
| 516 | |
| 517 | stringstream body; |
| 518 | |
| 519 | // check whether etagList or uploadId are empty, |
| 520 | // no matter we have done this in upper-layer or not. |
| 521 | if (etagArray.empty() || uploadId.empty()) { |
| 522 | return false; |
| 523 | } |
| 524 | |
| 525 | body << "<CompleteMultipartUpload>\n"; |
| 526 | for (uint64_t i = 0; i < etagArray.size(); ++i) { |
| 527 | body << " <Part>\n <PartNumber>" << i + 1 << "</PartNumber>\n <ETag>" << etagArray[i] |
| 528 | << "</ETag>\n </Part>\n"; |
| 529 | } |
| 530 | body << "</CompleteMultipartUpload>"; |
| 531 | |
| 532 | headers.Add(HOST, s3Url.getHostForCurl()); |
| 533 | headers.Add(CONTENTTYPE, "application/xml"); |
| 534 | |
| 535 | char contentSha256[SHA256_DIGEST_STRING_LENGTH]; // 65 |
| 536 | sha256_hex(body.str().c_str(), contentSha256); |
| 537 | headers.Add(X_AMZ_CONTENT_SHA256, contentSha256); |
| 538 | |
| 539 | headers.Add(CONTENTLENGTH, std::to_string((unsigned long long)body.str().length())); |
| 540 | |
| 541 | queryString << "uploadId=" << uploadId; |
| 542 | |
| 543 | SignRequestV4("POST", &headers, s3Url.getRegion(), s3Url.getPathForCurl(), queryString.str(), |
| 544 | this->params.getCred()); |
| 545 | |
| 546 | stringstream urlWithQuery; |
| 547 | urlWithQuery << s3Url.getFullUrlForCurl() << "?uploadId=" << uploadId; |
| 548 | |
| 549 | string bodyString = body.str(); |
| 550 | Response resp = this->postResponseWithRetries( |
| 551 | urlWithQuery.str(), headers, vector<uint8_t>(bodyString.begin(), bodyString.end())); |
| 552 | |
| 553 | if (resp.getStatus() == RESPONSE_OK) { |
| 554 | return true; |
| 555 | } else if (resp.getStatus() == RESPONSE_ERROR) { |
| 556 | S3MessageParser s3msg(resp); |
| 557 | S3_DIE(S3LogicError, s3msg.getCode(), s3msg.getMessage()); |
| 558 | } else { |
| 559 | S3_DIE(S3RuntimeError, "unexpected response status"); |
| 560 | } |
| 561 | } |
| 562 | |
| 563 | bool S3InterfaceService::abortUpload(const S3Url &s3Url, const string &uploadId) { |
| 564 | HTTPHeaders headers; |