1616#else 
1717#include  < unistd.h> 
1818#endif 
19+ #ifdef  USE_OPENSSL_MD5
20+ #include  < openssl/md5.h> 
21+ #endif 
1922
2023#include  " Poco/DigestStream.h" 
2124#include  " Poco/DirectoryIterator.h" 
@@ -854,9 +857,10 @@ CosResult ObjectOp::UploadObjectResumableSingleThreadSync(const PutObjectByFileR
854857  std::vector<uint64_t > part_numbers;
855858
856859  PutObjectByFileResp upload_resp;
860+   uint64_t  crc64_origin = 0 ;
857861  CosResult upload_result =
858862      SingleThreadUpload (req, resume_uploadid, already_exist_parts, resume_flag,
859-                         &etags, &part_numbers, &upload_resp);
863+                         &etags, &part_numbers, &upload_resp, crc64_origin );
860864
861865  //  Notice the cancel way not need to abort the uploadid
862866  if  (!upload_result.IsSucc ()) {
@@ -885,16 +889,6 @@ CosResult ObjectOp::UploadObjectResumableSingleThreadSync(const PutObjectByFileR
885889  //  check crc64 if needed
886890  if  (req.CheckCRC64 () && comp_result.IsSucc () &&
887891      !comp_resp.GetXCosHashCrc64Ecma ().empty ()) {
888-     uint64_t  crc64_origin = 0 ;
889- #if  defined(_WIN32)
890-     if  (req.IsWideCharPath ()) {
891-       crc64_origin = FileUtil::GetFileCrc64 (req.GetWideCharLocalFilePath ());
892-     } else  {
893-       crc64_origin = FileUtil::GetFileCrc64 (req.GetLocalFilePath ());
894-     }
895- #else 
896-     crc64_origin = FileUtil::GetFileCrc64 (req.GetLocalFilePath ());
897- #endif 
898892    uint64_t  crc64_server_resp =
899893        StringUtil::StringToUint64 (comp_resp.GetXCosHashCrc64Ecma ());
900894    if  (crc64_server_resp != crc64_origin) {
@@ -1915,7 +1909,8 @@ CosResult ObjectOp::SingleThreadUpload(
19151909    const  PutObjectByFileReq& req, const  std::string& upload_id,
19161910    const  std::vector<std::string>& already_exist_parts, bool  resume_flag,
19171911    std::vector<std::string>* etags_ptr,
1918-     std::vector<uint64_t >* part_numbers_ptr, PutObjectByFileResp* resp) {
1912+     std::vector<uint64_t >* part_numbers_ptr, PutObjectByFileResp* resp,
1913+     uint64_t & crc64) {
19191914  CosResult result;
19201915  std::string path = " /"   + req.GetObjectName ();
19211916  std::string host = CosSysConfig::GetHost (GetAppId (), m_config->GetRegion (),
@@ -1976,6 +1971,7 @@ CosResult ObjectOp::SingleThreadUpload(
19761971  SDK_LOG_DBG (" upload data, part_size=%"   PRIu64
19771972              " , file_size=%"   PRIu64, part_size, file_size);
19781973
1974+   crc64 = 0 ;
19791975  //  3. 单线程upload
19801976  {
19811977    uint64_t  part_number = 1 ;
@@ -1990,6 +1986,10 @@ CosResult ObjectOp::SingleThreadUpload(
19901986                    " , offset=%"   PRIu64 " , len=%"   PRIu64,
19911987                    part_number, file_size, offset, read_len);
19921988
1989+         //  提前计算整个文件的crc64,用于整个合并分块完成后做crc64校验
1990+         crc64 = CRC64::CalcCRC (crc64, static_cast <void *>(file_content_buf),
1991+                              static_cast <size_t >(read_len));
1992+ 
19931993        //  Check the resume
19941994
19951995        if  (resume_flag && !already_exist_parts[part_number].empty ()) {
@@ -2013,6 +2013,15 @@ CosResult ObjectOp::SingleThreadUpload(
20132013          if  (req.GetHeader (" x-cos-traffic-limit"  ) != " "  ) {
20142014            upload_part_req.SetTrafficLimit (req.GetHeader (" x-cos-traffic-limit"  ));
20152015          }
2016+ 
2017+         #ifdef  USE_OPENSSL_MD5
2018+           //  提前计算Content-MD5
2019+           unsigned  char  digest[MD5_DIGEST_LENGTH];
2020+           MD5 ((const  unsigned  char  *)file_content_buf, read_len, digest);
2021+           std::string digest_str ((const  char *)digest, MD5_DIGEST_LENGTH);
2022+           upload_part_req.AddHeader (" Content-MD5"  , CodecUtil::Base64Encode (digest_str));
2023+         #endif 
2024+ 
20162025          qcloud_cos::UploadPartDataResp upload_part_resp;
20172026          qcloud_cos::CosResult upload_part_result = UploadPartData (upload_part_req, &upload_part_resp);
20182027
0 commit comments