Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upload file to FTP server (Ubuntu) #51

Open
victoriastraberg opened this issue Apr 19, 2023 · 9 comments
Open

Upload file to FTP server (Ubuntu) #51

victoriastraberg opened this issue Apr 19, 2023 · 9 comments

Comments

@victoriastraberg
Copy link

victoriastraberg commented Apr 19, 2023

Hi! @embeddedmz

Im working with c++ code in Ubuntu and want to upload files/images to my FTP server. See attached images. How could I solve this? I have installed libcurl.

ftp

terminal

Thanks in advance!

@embeddedmz
Copy link
Owner

Hello,

First of all, you must put your code inside a function (ex: int main() { // put code here }).

I ll try to give you an example before the end of the day that you can build on Ubuntu without CMake.

If you don't connect a secure FTP server (SFTP, FTPS/FTPES), you don't need to use the methode SetInsecure(true). Also, if the FTP server is not an active one (very rare), you must not set active to true.

Regards.

@victoriastraberg
Copy link
Author

Thank you very much!! I will put the code inside an upload() function which will have an input argument as a string. The input variable is a JPG image. @embeddedmz

@embeddedmz
Copy link
Owner

embeddedmz commented Apr 19, 2023

@victoriastraberg I tested this example with an FTP server hosted at 192.168.1.17:21 on my local network and a user account named "test" with a password "0123456789C++" :

#include "FTPClient.h"

#include <iostream>

using namespace embeddedmz;

int main()
{
     // CFTPClient is allocated on the main function's stack
     CFTPClient ftpClient([](const std::string& strLogMsg)
     { std::cout << strLogMsg << std::endl; });
     
     // Initialize a session
     ftpClient.InitSession("192.168.1.17", 21, "test", "0123456789C++");

     // Create dummy test file
     std::ofstream testFileStream("test_upload.txt");
     testFileStream << "This file is uploaded via FTPClient-C++ API.\n"
                       "If this file exists, that means that the test is passed.\n";
     testFileStream.close();

     // Upload "test_upload.txt" (relative path to the executable) to "/uploaded_file.txt" (distant file path on the FTP server)
     if (ftpClient.UploadFile("test_upload.txt", "uploaded_file.txt"))
     {
         std::cout << "OK.\n";
     }
     else
     {
         std::cout << "Error.\n";      
     }
     
     // Explicit session cleanup
     ftpClient.CleanupSession();
     
     // Remove dummy test file
     remove("test_upload.txt");
}

You can copy/paste that code in a main.cpp file that you can place in the same directory as the ftpclient-cpp/FTP/ and run this command in a terminal to compile the program :
g++ -DLINUX main.cpp FTPClient.cpp CurlHandle.cpp -lcurl -o testUpload

Explanations :
-DLINUX : you define a preprocessor macro 'LINUX' so you can enable the parts of the code that are intended for a Linux platform (it's like adding #define LINUX before #include "FTPClient.h").
-lcurl : You link the executable to libcurl shared object (library).
-o testUpload : The generated program will be named testUpload
I didn't add an argument to tell the compiler where the header files (.h) are (the argument is -I. the dot represents the current directory) since they are in the same directory as the source code cpp files.

To run the program :
./testUpload

@victoriastraberg
Copy link
Author

It works! Thank you! @embeddedmz

See attached image below. I get these warnings when I write -DLINUX and when I remove -DLINUX I get "could not find #include <direct.h>..." How come?

screenshot

@embeddedmz
Copy link
Owner

embeddedmz commented Apr 24, 2023

LINUX preprocessor macro must be defined because in the header file there's these preprocessor instructions

#ifndef LINUX                            // If LINUX macro is NOT defined (e.g. we are compiling on MS Visual Studio) include <direct.h>
#include <direct.h>                  // mkdir() function in defined in <direct.h> on Windows platform
#endif

<direct.h> is a header that exists only with Microsoft Visual Studio C/C++ API and contains mkdir() function used to create a directory. LINUX macro must be defined so that the C++ GNU compiler's preprocessor doesn't include it in the code that will be compiled.

You can ignore the warnings, they are related to obsolete elements in newer versions of libcurl. You can't see them if the LINUX macro processor is not defined because the compiler stops when it comes across the error related to <direct.h>.

@victoriastraberg
Copy link
Author

@embeddedmz Ok, thanks! :) Unfortunately I get every file stored in my local folder. How could I just upload the file without saving it locally?

@embeddedmz
Copy link
Owner

You can specify the absolute path to the file e.g. "/home/user/test_upload.txt". In the example above, I used a relative path but you can also use absolute paths.

Example :
ftpClient.UploadFile("/home/user/test_upload.txt", "ftp_upload_dir/uploaded_file.txt")

On Windows :
ftpClient.UploadFile("C:\\test_upload.txt", "ftp_upload_dir/uploaded_file.txt")

@victoriastraberg
Copy link
Author

victoriastraberg commented Apr 26, 2023

@embeddedmz

Yes exactly. I already do like this - the problem is that the image still gets saved in the code folder. See here:

image1

@embeddedmz
Copy link
Owner

embeddedmz commented Apr 26, 2023

Can you show me the code using the upload() function ? (by the way, you don't need to use c_str() method when concatenating strings and when using UploadFile()).

I want to see how the image is stored in memory.

UploadFile has this "overloading" :

   bool UploadFile(std::istream &inputStream, const std::string &strRemoteFile, const bool &bCreateDir = false,
                   curl_off_t fileSize = -1) const;

Depending on the code that retrieves an image from the camera and keeps it somewhere in memory, I could help you write the code that uses this overloading. Something like this :

      unsigned char* mybuffer;
      size_t length;
      // allocate, fill, set length, as before

     std::string data(mybuffer, length);
     std::istringstream mb(data);

      // Upload stream
      ftpClient.UploadFile(mb, "image.jpg");

I can also add an overloading to the API having this signature if you want :
bool CFTPClient::UploadFile(const unsigned char* dataPtr, const size_t dataLength, const std::string &strRemoteFile, const bool &bCreateDir)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants