[aws-sdk-cpp] [s3]使用getObject下载二进制文件

时间:2019-04-10 08:46:53

标签: c++ amazon-s3 download binary-data aws-sdk-cpp

正在尝试编写一些代码以从AWS S3服务器下载二进制文件。

我在下面编写了该代码,大约200MB的二进制文件看起来还可以,所以我认为它可以工作。

但是对于200MB〜这样的大文件,它将被下载,但仅文件的前部。

例如,仅下载视频文件(1.2GB)的前端(460MB〜700MB)。

为什么会发生这种情况?是关于ofstream功能?

context.Response.Write(rechargeDT.Rows[i]["RechargeCode"] + "\t" + Amount + "\t" + rechargeDT.Rows[i]["SerialNumber"].ToString() + "\t" + qrCodeImage + "\t");

2 个答案:

答案 0 :(得分:1)

  

即使是现在,我也不知道为什么它不起作用。

因为在您的第一个示例中,它将整个文件存储在内存中。 在第二个代码段中,您通过使用fstream作为响应流来做正确的事情。因此,它现在立即写入磁盘。

答案 1 :(得分:0)

即使是现在,我也不知道为什么它不起作用。

但是我将方法更改为如下所示,并且可以正常工作。


该代码使下载的块数据直接发送到光盘。

因此它不会占用太多内存(大约10〜30MB)

// 3. file download from s3
   {
          string strTargetPath = hThis->m_strTargetPath;
          Aws::SDKOptions options;
          options.loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Trace;
          Aws::InitAPI(options);
          {
                 // Download from s3 using GetObject

                 char *bucket_name = "nemodax-upload-dev";
                 std::string key_name = strTargetPath;
                 Aws::Client::ClientConfiguration clientConfig;
                 clientConfig.region = "ap-northeast-2";
                 //Aws::S3::S3Client s3_client;
                 std::unique_ptr< Aws::S3::S3Client > s3_client(new Aws::S3::S3Client(clientConfig));
                 Aws::S3::Model::GetObjectRequest object_request;
                 object_request.WithBucket(bucket_name).WithKey(key_name.c_str());

                 // parse file name from path
                 string str_arr[1000];
                 int str_cnt = 0;
                 char *str_buff = new char[1000];
                 strcpy(str_buff, strTargetPath.c_str());
                 char *tok = strtok(str_buff, "/");
                 while (tok != nullptr) {
                       str_arr[str_cnt++] = string(tok);
                       tok = strtok(nullptr, "/");
                 }
                 string fileName = str_arr[str_cnt - 1];
                 // 다운로드하면서 스트림을 아래 fileName으로 지정하는 파일로 바로바로 저장 그래서 메모리를 별로 안먹는다.
                 object_request.SetResponseStreamFactory(
                       [=]() {
                       //return Aws::New<Aws::FStream>("S3DOWNLOAD", hThis->m_origFileName, std::ios_base::out | std::ios_base::binary);
                       return Aws::New<Aws::FStream>("S3DOWNLOAD", fileName, std::ios_base::out | std::ios_base::binary);
                 }
                 );
                 auto get_object_outcome = s3_client.get()->GetObject(object_request);
                 if (get_object_outcome.IsSuccess())
                 {
                       std::string strFileName = fileName;
                       hThis->m_origFileNameString = strFileName;
                       hThis->m_origFileName = strFileName.c_str();
                       hThis->Logger(CPrePackagerDlg::currentDateTime() + "file size: " + std::to_string(get_object_outcome.GetResult().GetContentLength()) + "\n");
                       hThis->Logger(CPrePackagerDlg::currentDateTime() + "download is done\n");
                       // 다운로드된 원본 파일 경로를 멤버변수로 등록-> 추후 암호화때 이 경로를 참조함.
                       // 파일경로 + 파일명 조합
                       TCHAR programpath[_MAX_PATH];
                       GetCurrentDirectory(_MAX_PATH, programpath);
                       hThis->m_valOriginFolderPath.Format(_T("%s\\"), programpath);
                       hThis->m_valOriginFolderPath += hThis->m_origFileName;
                 }
                 else
                 {
                       hThis->Logger(CPrePackagerDlg::currentDateTime() + "s3 download error: " +
                              get_object_outcome.GetError().GetExceptionName() + " " +
                              get_object_outcome.GetError().GetMessage() + "\n");
                       hThis->runSignal = CPrePackagerDlg::RunSignal::STAT_RUN_STOP;
                 }

          }
          Aws::ShutdownAPI(options);
   }