首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用CURL下载图像

使用CURL下载图像
EN

Code Review用户
提问于 2016-12-21 21:37:51
回答 1查看 3.4K关注 0票数 3

我编写了这个类,它下载图像,其URL是从本地.txt文件中读取的。我很想确保我的代码是安全和高效的。

代码语言:javascript
复制
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include<cassert>
#include <algorithm>
#include <numeric>
#include <functional>
#include <curl/curl.h>

class DownloadTesting
{
  private:
    CURL *curl;
    FILE *file;
    CURLcode response;
    char outfilename[FILENAME_MAX];
    int count {0};
    std::vector<char*> URLS; //Stores the urls
    auto DownloadImage(const char *url) -> void;
    auto Convert(const std::string &s) -> char*;
    auto ReadDataStore() -> void;
    static auto WriteData(void *ptr, size_t size, size_t nmemb, FILE *stream) -> size_t;
  public:
    DownloadTesting();
    ~DownloadTesting();
    auto Interface() -> void;
};


DownloadTesting::DownloadTesting(){};

DownloadTesting::~DownloadTesting()
{
   if(!URLS.empty()) //Delete raw pointers
   {
     std::for_each(URLS.begin(),URLS.end(),[](char* url){delete url;});
   }
}

auto DownloadTesting::WriteData(void *ptr, size_t size, size_t nmemb, FILE *stream) -> size_t //Write data into file 
{
   size_t written {fwrite(ptr, size, nmemb, stream)};
   return written;
}

auto DownloadTesting::Convert(const std::string &s) -> char* //Convert url from std::string to raw char pointer
{
  char *pc {new char[s.size()+1]};
  std::strcpy(pc,s.c_str());
  return pc;
}

auto DownloadTesting::ReadDataStore() -> void
{
  std::vector<std::string> storage_vector;
  std::string storage_string;
  std::ifstream storage_file {"./imagestore/urlstore.txt"};
  if(storage_file.is_open()) //Open local file
  {
     while(getline (storage_file,storage_string)) //Read each line
     {
       storage_vector.push_back(storage_string); //Storage each line in vector
     }
     storage_file.close();
  }
  std::transform(storage_vector.begin(), storage_vector.end(), std::back_inserter(URLS), [this](const std::string url){return this->Convert(url);}); //Perform conversion function on each url
}

auto DownloadTesting::DownloadImage(const char *url) -> void
{
  count++; //Use a counter to name each downloaded file
  std::string name {std::to_string(count)}; //Convert int to string
  strcpy(outfilename, name.c_str()); //Convert std::string to [char]

  curl = curl_easy_init(); //Initialise curl
  if(curl)
  {
    file = fopen(outfilename,"wb");
    curl_easy_setopt(curl, CURLOPT_URL, url);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &DownloadTesting::WriteData);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
    response = curl_easy_perform(curl);
    curl_easy_cleanup(curl); //Clean up curl
    fclose(file); //Close file
  }
}


auto DownloadTesting::Interface() -> void
{
  this -> ReadDataStore(); //Read in the data
  assert(!URLS.empty()); //Ensure data is not empty
  std::for_each(URLS.begin(),URLS.end(), [this](const char* url){return this -> DownloadImage(url);}); //Perform download for each url
}

int main()
{
  DownloadTesting DTO;
  DTO.Interface();
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2016-12-21 22:09:21

语言特征

您正在尝试使用新的C++语言特性,但您似乎没有有效地使用它们。

  • 这个: std::for_each(URLS.begin(),URLS.end(),{返回这个-> DownloadImage( url );});可以用一个简单的: for (auto&url: URLS) DownloadImage(url)代替。
  • 仅将auto用于方法声明以指定行尾的返回类型是令人费解的。

内存管理

规则5:需要自定义析构函数来处理资源(De)分配的类,很可能还需要自定义复制构造函数、赋值操作符和移动构造函数/赋值运算符。

创建字符串的原始副本只是为了存储指向字符的原始指针。当您需要将原始指针传递到库并让string类管理内存时,只需使用string.c_str()

CURL

通过回调将数据写入文件,并要求curl将数据写入文件,这看起来像是重复的工作。有什么原因吗?

OOP

这个类不是面向对象设计的好例子。唯一可用的公共方法Interface并不表示它可能会做什么。作为一个函数,整个代码可能会更好。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/150537

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档