in sdk/src/resumable/ResumableUploader.cc [311:440]
int ResumableUploader::prepare(FileCompleteOutcome& completeOutcome)
{
determinePartSize();
FileCreateOutcome outcome;
// rapid upload
if (client_->configuration().enableRapidUpload) {
// caculate pre hash
uint64_t preHashBlockSize = 1024;
if (preHashBlockSize > request_.FileSize()) {
preHashBlockSize = request_.FileSize();
}
auto content = GetFstreamByPath(request_.FilePath(), request_.FilePathW(),
std::ios::in | std::ios::binary);
char streamBuffer[1024];
uint64_t readSize = 0;
if (!content->good()) {
completeOutcome = FileCompleteOutcome(PdsError("ReadFileError", "Failed to read input file"));
return -1;
}
content->read(streamBuffer, preHashBlockSize);
readSize = static_cast<uint64_t>(content->gcount());
content->close();
if (readSize != preHashBlockSize) {
completeOutcome = FileCompleteOutcome(PdsError("ReadFileError", "Failed to read enough size for caculate pre hash"));
return -1;
}
std::string preHashSHA1 = ComputeContentSha1(streamBuffer, preHashBlockSize);
// check pre hash request
auto fileCreatePreCheckReq = FileCreateRequest(request_.DriveID(), request_.ParentFileID(), request_.Name(),
request_.FileID(), request_.CheckNameMode(), request_.FileSize());
fileCreatePreCheckReq.setPreHash(preHashSHA1);
fileCreatePreCheckReq.setUserTags(request_.UserTags());
fileCreatePreCheckReq.setHidden(request_.Hidden());
auto fileCreatePreCheckOutcome = FileCreateWrap(fileCreatePreCheckReq);
if (!fileCreatePreCheckOutcome.isSuccess()) {
// check pre hash error
if (fileCreatePreCheckOutcome.error().Code() != "PreHashMatched") {
completeOutcome = FileCompleteOutcome(fileCreatePreCheckOutcome.error());
return -1;
}
// check pre hash matched, rapid upload
std::string hashSHA1;
if (0 != ComputeFileSha1(completeOutcome, hashSHA1)){
return -1;
}
// rapid upload request
auto fileCreateRapidUploadReq = FileCreateRequest(request_.DriveID(), request_.ParentFileID(), request_.Name(),
request_.FileID(), request_.CheckNameMode(), request_.FileSize());
fileCreateRapidUploadReq.setContentHash(hashSHA1);
fileCreateRapidUploadReq.setUserTags(request_.UserTags());
fileCreateRapidUploadReq.setHidden(request_.Hidden());
auto fileCreateRapidUploadOutcome = FileCreateWrap(fileCreateRapidUploadReq);
if (!fileCreateRapidUploadOutcome.isSuccess()) {
completeOutcome = FileCompleteOutcome(fileCreateRapidUploadOutcome.error());
return -1;
}
// rapid upload success
if (fileCreateRapidUploadOutcome.result().RapidUpload()) {
FileCompleteResult result(fileCreateRapidUploadOutcome.result());
completeOutcome = FileCompleteOutcome(result);
return -1;
}
// failed to rapid upload, upload data
outcome = fileCreateRapidUploadOutcome.result();
}
else {
// pre hash check not matched, upload data
outcome = fileCreatePreCheckOutcome.result();
}
}
else {
// create by upload data
FileCreateRequest fileCreateReq = FileCreateRequest(request_.DriveID(), request_.ParentFileID(), request_.Name(),
request_.FileID(), request_.CheckNameMode(), fileSize_);
fileCreateReq.setUserTags(request_.UserTags());
fileCreateReq.setHidden(request_.Hidden());
auto fileCreateOutcome = FileCreateWrap(fileCreateReq);
if (!fileCreateOutcome.isSuccess()) {
completeOutcome = FileCompleteOutcome(fileCreateOutcome.error());
return -1;
}
outcome = fileCreateOutcome.result();
}
if (outcome.result().Exist()) {
completeOutcome = FileCompleteOutcome(PdsError("SameNameFileExist", "Same name file exist."));
return -1;
}
if (hasRecordPath()) {
initRecordInfo();
record_.fileID = outcome.result().FileID();
record_.uploadID = outcome.result().UploadID();
Json::Value root;
root["opType"] = record_.opType;
root["driveID"] = record_.driveID;
root["fileID"] = record_.fileID;
root["uploadID"] = record_.uploadID;
root["name"] = record_.name;
root["filePath"] = record_.filePath;
root["taskID"] = record_.taskID;
root["mtime"] = record_.mtime;
root["size"] = record_.size;
root["partSize"] = record_.partSize;
root["parts"].resize(0);
std::stringstream ss;
ss << root;
std::string md5Sum = ComputeContentETag(ss);
root["md5Sum"] = md5Sum;
auto recordStream = GetFstreamByPath(recordPath_, recordPathW_, std::ios::out);
if (recordStream->is_open()) {
*recordStream << root;
recordStream->close();
}
}
return 0;
}