FileCompleteOutcome PdsClientImpl::ResumableFileUpload()

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();
    }
}