Kingfisher Phuoc
Kingfisher Phuoc

Reputation: 8200

Libcurl error with FTP upload in ubuntu C++

In windows, this code works file, but now, I want to convert it into ubuntu:

  // callback read function to upload file from local to ftp server
size_t read_callback (void* ptr, size_t size, size_t nmemb, FILE *stream){
    //return fread(ptr,size,nmemb, (FILE*) stream);
    return fread(ptr,size,nmemb,stream);
}

// get file name from a path
string FTPClientConnector::getFileName(string path){
    int length = path.size();
    for(int i = length - 1; i >= 0; i--){
        if(path[i] == '/' || path[i] == '\\'){
            return path.substr(i+1, length-i-1);
        }
    }
}

//function to upload a file to FTP server
int FTPClientConnector::uploadFile(string filePath, string serverPath ){
    CURL *curl;
    CURLcode res;
    FILE *hd_src;
    struct stat file_info;
    curl_off_t fsize;

    char* local_file = new char[filePath.size()+1];
    std::copy(filePath.begin(), filePath.end(), local_file);
    local_file[filePath.size()] = '\0';

    // stat the local file
    if(stat(local_file, &file_info)){
        printf("couldn't open file\n");
        delete local_file;
        return -1;
    }

    // convert URL and username and password to connect to remote server
    string urlPath = this->hostName + serverPath;
    urlPath += getFileName(filePath);
    char *url = new char[urlPath.size() + 1];
    std::copy(urlPath.begin(), urlPath.end(), url);
    url[urlPath.size()] = '\0';

    string userAndPassString = this->userName + ":" + this->password;
    char* usernameAndPassword = new char[userAndPassString.size() +1];
    std::copy(userAndPassString.begin(), userAndPassString.end(), usernameAndPassword);
    usernameAndPassword[userAndPassString.size()] = '\0';

    // get the file to open
    hd_src = fopen(local_file, "rb");

    curl_global_init(CURL_GLOBAL_ALL);
    curl = curl_easy_init();
    if(curl){

        /* specify target */
        curl_easy_setopt(curl,CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_PORT, this->port);
        curl_easy_setopt(curl, CURLOPT_USERPWD, usernameAndPassword);

          /* we want to use our own read function */
        curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);

        /* enable uploading */
        curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);

        /* now specify which file to upload */
        curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);

        /* Now run off and do what you've been told! */
        res = curl_easy_perform(curl);

        if(res != CURLE_OK){
            printf("Upload file failed!\n");
            delete local_file;
            delete url;
            delete usernameAndPassword;
            return -1;
        }
        curl_easy_cleanup(curl);
    }
    fclose(hd_src);

    delete local_file;
    delete url;
    delete usernameAndPassword;
    return 0;
}    

This is what I call in main.cpp:

FTPClientConnector connector(host,user,password,port);
connector.uploadFile("xml/kingfisher.xml", "/xml_test_upload");

The code above doesn't work in Ubuntu with errors:

220 ProFTPD 1.3.4a Server (Debian) [::ffff:10.244.31.244]
500 PUT not understood
500 AUTHORIZATION: not understood
500 HOST: not understood
550 */*: Forbidden command argument
500 TRANSFER-ENCODING: not understood
500 EXPECT: not understood
500 Invalid command: try being more creative
500 2A2 not understood

Edit: This is my Makefile:

uploader:
    g++ -o uploader FTPClientConnector.cpp main.cpp -lcurl

Upvotes: 0

Views: 1559

Answers (2)

Daniel Stenberg
Daniel Stenberg

Reputation: 58094

The output seems to indicate that you speak HTTP to a FTP server. Make sure your URL properly uses a FTP:// prefix for FTP, as without a protocol prefix libcurl guesses which protocol you want and it defaults to HTTP...

Upvotes: 1

CrazyCasta
CrazyCasta

Reputation: 28352

It appears from your comments that you need to use IPv4. Add this to your list of setopt calls:

curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);

Upvotes: 1

Related Questions