in sdk/src/PdsClientImpl.cc [639:796]
FileCompleteOutcome PdsClientImpl::ResumableFileUpload(const FileUploadRequest &request) const
{
const auto& reqeustBase = static_cast<const PdsResumableBaseRequest &>(request);
int code = reqeustBase.validate();
if (code != 0) {
return FileCompleteOutcome(PdsError("ValidateError", reqeustBase.validateMessage(code)));
}
if (request.FileSize() <= request.PartSize())
{
PartInfoReqList partInfoReqList;
PartInfoReq info(1, request.FileSize(), 0, request.FileSize()-1);
partInfoReqList.push_back(info);
FileCreateResult fileCreateResult;
// rapid upload
if (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()) {
return FileCompleteOutcome(PdsError("ReadFileError", "Failed to read input file"));
}
content->read(streamBuffer, preHashBlockSize);
readSize = static_cast<uint64_t>(content->gcount());
content->close();
if (readSize != preHashBlockSize) {
return FileCompleteOutcome(PdsError("ReadFileError", "Failed to read enough size for caculate pre hash"));
}
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.setPartInfoList(partInfoReqList);
fileCreatePreCheckReq.setUserTags(request.UserTags());
fileCreatePreCheckReq.setHidden(request.Hidden());
auto fileCreatePreCheckOutcome = FileCreate(fileCreatePreCheckReq);
if (!fileCreatePreCheckOutcome.isSuccess()) {
// check pre hash error
if (fileCreatePreCheckOutcome.error().Code() != "PreHashMatched") {
return FileCompleteOutcome(fileCreatePreCheckOutcome.error());
}
// check pre hash matched, rapid upload
auto content = GetFstreamByPath(request.FilePath(), request.FilePathW(),
std::ios::in | std::ios::binary);
std::string hashSHA1 = ComputeContentSha1(*content);
content->close();
// rapid upload request
auto fileCreateRapidUploadReq = FileCreateRequest(request.DriveID(), request.ParentFileID(), request.Name(),
request.FileID(), request.CheckNameMode(), request.FileSize());
fileCreateRapidUploadReq.setContentHash(hashSHA1);
fileCreateRapidUploadReq.setPartInfoList(partInfoReqList);
fileCreateRapidUploadReq.setUserTags(request.UserTags());
fileCreateRapidUploadReq.setHidden(request.Hidden());
auto fileCreateRapidUploadOutcome = FileCreate(fileCreateRapidUploadReq);
if (!fileCreateRapidUploadOutcome.isSuccess()) {
return FileCompleteOutcome(fileCreateRapidUploadOutcome.error());
}
// rapid upload success
if (fileCreateRapidUploadOutcome.result().RapidUpload()) {
FileCompleteResult result(fileCreateRapidUploadOutcome.result());
return FileCompleteOutcome(result);
}
// failed to rapid upload, upload data
fileCreateResult = fileCreateRapidUploadOutcome.result();
} else {
// pre hash check not matched, upload data
fileCreateResult = fileCreatePreCheckOutcome.result();
}
} else {
// create by upload data
auto fileCreateReq = FileCreateRequest(request.DriveID(), request.ParentFileID(), request.Name(),
request.FileID(), request.CheckNameMode(), request.FileSize());
fileCreateReq.setPartInfoList(partInfoReqList);
fileCreateReq.setUserTags(request.UserTags());
fileCreateReq.setHidden(request.Hidden());
auto fileCreateOutcome = FileCreate(fileCreateReq);
if (!fileCreateOutcome.isSuccess()) {
return FileCompleteOutcome(fileCreateOutcome.error());
}
fileCreateResult = fileCreateOutcome.result();
}
if (fileCreateResult.Exist()) {
return FileCompleteOutcome(PdsError("SameNameFileExist", "Same name file exist."));
}
std::string fileID = fileCreateResult.FileID();
std::string uploadID = fileCreateResult.UploadID();
PartInfoRespList partInfoRespList = fileCreateResult.PartInfoRespList();
if (partInfoRespList.size() == 0) {
return FileCompleteOutcome(PdsError("GetUploadUrlError", "Get Upload url empty."));
}
std::string uploadURl = partInfoRespList[0].UploadUrl();
// upload data
auto content = GetFstreamByPath(request.FilePath(), request.FilePathW(),
std::ios::in | std::ios::binary);
DataPutByUrlRequest putPartRequest(uploadURl, content);
if (request.TransferProgress().Handler) {
putPartRequest.setTransferProgress(request.TransferProgress());
}
if (request.ProgressControl().Handler) {
putPartRequest.setProgressControl(request.ProgressControl());
}
auto putOutCome = DataPutByUrl(putPartRequest);
auto controller = request.ProgressControl();
if (controller.Handler) {
int32_t controlFlag = controller.Handler(controller.UserData);
if (controlFlag == ProgressControlStop) {
return FileCompleteOutcome(PdsError("ClientError:100003", "Upload stop by upper."));
}
if (controlFlag == ProgressControlCancel) {
return FileCompleteOutcome(PdsError("ClientError:100004", "Upload cancel by upper."));
}
}
if (!putOutCome.isSuccess()) {
return FileCompleteOutcome(putOutCome.error());
}
// pds complete file
FileCompleteRequest completeRequest(request.DriveID(), fileID, uploadID);
auto completeOutcome = FileComplete(completeRequest);
if (!completeOutcome.isSuccess()) {
return FileCompleteOutcome(completeOutcome.error());
}
// check size
uint64_t uploadedfileSize = completeOutcome.result().Size();
if (request.FileSize() != uploadedfileSize) {
return FileCompleteOutcome(PdsError("FileSizeCheckError", "Upload data check size fail."));
}
return completeOutcome;
}
else {
ResumableUploader uploader(request, this);
return uploader.Upload();
}
}