Home > Back-end >  Poco::Net::FTPClientSession uploading blank, 0-byte copy of the actual target file
Poco::Net::FTPClientSession uploading blank, 0-byte copy of the actual target file

Time:08-29

I am currently writing a class which handles a variety of FTP requests and I'm using Poco's FTPClientSession class. I've managed to get most of the stuff I needed to work, however I'm facing an issue regarding uploading files to the server.

int  __fastcall upload(String sLocalPath,
        String sLocalFile, // String can be substituted by std::string here, basically the same thing
        String sRemotePath,
        String sRemoteFile,
        String& sErr,
        int    iMode,
        bool   bRemoveFile)
    {
        try
        {
            // replace backslashes with forward slashes in the filepath strings,
            // append one if necessary
            std::string sLocalFilepath = sLocalPath.c_str();
            std::replace(sLocalFilepath.begin(), sLocalFilepath.end(), '\\', '/');

            if (sLocalFilepath[sLocalFilepath.size() - 1] != '/')
                sLocalFilepath  = "/";
            sLocalFilepath  = sLocalFile.c_str();

            std::string sRemoteFilepath = sRemotePath.c_str();
            std::replace(sRemoteFilepath.begin(), sRemoteFilepath.end(), '\\', '/');
            
            // traverses and/or creates directories in the server (this definitely works)
            FailsafeDirectoryCycler(sRemoteFilepath, "/");

            // upload the file
            m_Session.beginUpload(sLocalFilepath);
            m_Session.endUpload();

            // change the name if necessary
            if (sLocalFile != sRemoteFile)
            {
                std::string oldName = sLocalFile.c_str();
                std::string newName = sRemoteFile.c_str();
                m_Session.rename(oldName, newName);
            }

            // delete the local file if specified
            if (bRemoveFile)
                DeleteFileA((sLocalPath   sLocalFile).c_str());

            m_Session.setWorkingDirectory("/");

            return 0;
        }
        catch (Poco::Exception& e)
        {
            std::cout << e.displayText() << std::endl;
            return -1;
        }
    }

The above function also changes the file transfer mode (TYPE_TEXT or TYPE_BINARY), however I excluded it for clarity, as I am certain it works as intended. The call to this function looks as follows:

f.upload(".", "filename123.txt", "testdir1\\testdir2\\abc", "filenamenew.txt", err, 0, true);

The arguments indicate that the file to be transfered is ./filename.txt, and it will end up as /testdir1/testdir2/abc/filenamenew.txt, which is exactly what happens (the rest of the arguments doesn't matter in this case). However, my issue is, the local file contains a short string: abcdef. The file, which gets uploaded to the server, does not contain a single byte; it is blank.

I couldn't find an answer to this question other than there is insufficient space on the server, which is definitely not the issue in this case. I shall add that the server is hosted locally using XLight FTP Server. Has anyone encountered this kind of problem before?

CodePudding user response:

Turns out, Poco::Net::FTPClientSession::beginUpload() doesn't read the file on its own. It returns a reference to an std::ostream, to which you need to load the contents of the file yourself (e.g. using std::ifstream):

std::ifstream hFile(sLocalFilepath, std::ios::in);
std::string line;
std::ostream& os = m_Session.beginUpload(sRemoteFile.c_str());
while (std::getline(hFile, line))
    os << line;
hFile.close();
m_Session.endUpload();
  • Related