9

任何人都可以推荐一个体面的 SFTP 库来与 Windows C++ 应用程序一起使用吗?如果可以使用跨平台的,那就更好了,但这不是必需的。它用于商业应用程序,因此付费不是问题。

我正在使用支持 FTP-S 但不支持 SFTP 的出色的Ultimate TCP/IP库(是的,我知道,不是很混乱!)。

我遇到过Chilkat图书馆,它看起来很不错,但想知道是否还有其他人用过。

4

3 回答 3

11

查看libcurl

libcurl 是一个免费且易于使用的客户端 URL 传输库,支持 FTP、FTPS、HTTP、HTTPS、SCP、SFTP、TFTP、TELNET、DICT、LDAP、LDAPS 和 FILE。libcurl 支持 SSL 证书、HTTP POST、HTTP PUT、FTP 上传、基于 HTTP 表单的上传、代理、cookie、用户+密码身份验证(Basic、Digest、NTLM、Negotiate、Kerberos4)、文件传输恢复、http 代理隧道等等!

libcurl 是高度可移植的,它可以在多种平台上构建和工作,包括 Solaris、NetBSD、FreeBSD、OpenBSD、Darwin、HPUX、IRIX、AIX、Tru64、Linux、UnixWare、HURD、Windows、Amiga、OS/2、BeOs、Mac OS X、Ultrix、QNX、OpenVMS、RISC OS、Novell NetWare、DOS 等...

于 2008-12-11T17:58:06.797 回答
5

OpenSSH将是一个不错的选择。它是跨平台的,并附带 BSD 许可证,因此您可以在商业应用程序中使用它,而无需透露您的源代码。

于 2008-12-11T17:58:53.893 回答
5

您可以在 windows 下使用 libssh 进行 SFTP。编译时必须有 ssh.lib,执行程序时必须有 ssh.dll。它对我来说很好。此示例代码是使用 ssh1 的客户端,我还支持大文件(4GB 及更多)和暂停/恢复。客户端将与任何 ssh(和/或 SFTP)服务器一起使用。由于 stackoverflow 中消息长度的限制,我无法为您复制整个代码。

main()
{
pSFTPConnector  sshc = new  SFTPConnector(L".\\", L"127.0.0.1", 22, L"sftpuser",L"sftppassword");  // change the hostname , port , username, password to your sftp server, your credentials

FILE *nullfile = fopen("null", "w");  
sshc->setLogFile(nullfile);
sshc->setVerbosity(SSH_LOG_DEBUG);  // you can change the verbosity as appropriate for you

int i=  sshc->InitSession();
if (i != E_OK) wprintf(L"%s",sshc->errstring.c_str() );
i=sshc->ConnectSession();
if (i != E_OK) wprintf(L"%s", sshc->errstring.c_str());

i = sshc->InitSFTP();
if (i != E_OK) wprintf(L"%s", sshc->errstring.c_str());

i = sshc->SFTPrename("renamed_myfile.txt", "myfile.txt");  //change these file names
i = sshc->Makedir("sftpdir");
i = sshc->testUploadFile("myfile2.txt", "1234567890testfile");


// change these file names to whatever appropriate


i = sshc->SFTPreget("c:\\testdir\\reget_downloaded_CAR_HIRE_FINAL.jpg", "CAR_HIRE_FINAL.jpg", 64 * 1024);
sshc->setBlockTransferDelay(1);

i = sshc->GetSessionStatus();
i = sshc->SFTPreput("c:\\testdir\\CentOS-6.5-x86_64-bin-DVD1.iso", "reput_CentOS-6.5-x86_64-bin-DVD1.iso", 64 * 1024);
i = sshc->SFTPreput("c:\\testdir\\Reget_CentOS-6.5-x86_64-bin-DVD1.iso", "reput2_CentOS-6.5-x86_64-bin-DVD1.iso", 64 * 1024);

if (i != E_OK) wprintf(L"%s", sshc->errstring.c_str());
delete sshc;
getchar();
return 0;
}

这是类文件:

// filename ssh.h
// SFTP Connection class with Pause/Resume largfiles capability
// uses libssh for sftp functionality.
// Author Desphilboy
// Written 21 Sep 2014




// needed include files on a windows system
// for linux, native file open and read/write functions must be changed.


#include <libssh\libssh.h>
#include <libssh\sftp.h>
#include <Windows.h>
#include <string>
#include <fcntl.h>
#include  <sys\types.h>
#include <sys\stat.h>
#include <time.h>
#include <fstream>
#include <iostream>
#include <process.h>
using namespace std;


// constant to limit length of character strings
#define SHORT_BUFF_LEN          1024
#define INITIALBLOCKTRANSDELAY          10          // mili seconds, this is the delay that we put after  each block transfer to make it posssible for network to absorb the data.




// these values will be returned by functions to report error or success
typedef enum sshconerr{
    E_OK = 1, E_SESSION_ALOC = -1, E_SSH_CONNECT_ERR = -2, E_SFTP_ALLOC = -3, E_INIT_SFTP = -4, E_CREATE_DIR = -5, E_FILEOPEN_WRITE = -6, E_WRITE_ERR = -7
    , E_FILE_CLOSE = -8, E_FILE_OPEN_READ = -9, E_INVALID_PARAMS = -10, E_SFTP_ERR = -11, E_SFTP_READ_ERR = -12, E_SFTP_READBYTES_ERR = -13, E_GET_FILEINF = -14
    , E_LOCAL_FILE_NOTFOUND = -15, E_RENAME_ERR = -16, E_MEM_ALLOC = -17, E_LOCAL_FILE_READ = -18, E_LOCAL_FILE_RDWR = -19, E_REMOTEFILE_SEEK = -20
    , E_REMOTE_FILE_OPEN = -21, E_DELETE_ERR = -22, E_RENAME_LOCAL_FILE = -23, E_LOCAL_DELETE_FILE = -24, E_FILEOPEN_RDONLY = -25, E_SFTP_READ_EOF=-26
    ,E_AUTHENTICATE=-27                 ,E_UNKNOWN=-999 } ESSHERR;


// status of transfers;
typedef enum sftpstat{ ES_DONE=0 , ES_INPROGRESS , ES_FAILED, ES_STARTING, ES_PAUSED, ES_RESUMING, ES_CANCELLED,  ES_NONE  } ESFTPSTAT;

using namespace std;




// statistics about the transfer;
typedef struct transferstatstruct {
    string remote_file_name;
    string local_file_name;
    __int64  initially_transferred;
    __int64  total_size;
    __int64  transferred;
    __int64  averagebps;
    __int64 seconds_elapsed;
    __int64     seconds_remained;
    int percent;    
    ESFTPSTAT transferstate;
} TTransStat;


#define E_SESSION_NEW   -1



// these libraries are required
#pragma comment(lib, "ssh.lib")         // for ex4ecution in windows, ssh.dll is needed




// this is the main class that does the majority of the work

typedef class CSFTPConnector{

private:

    ssh_session  session;                 // ssh session
    sftp_session sftp;                      // sftp session
    sftp_file file;                         // structure for a remote file
    FILE *localfile;                        // not used in windows but could be local file pointer in UNIX
    FILE *logfile;                          // the file for writing logs, default is set to stderr
    string filename;                        // file name of the transfer;
    string localfilename;                   // file name of local file;
    string      tempfilename;               // a temporaty file name will be used during the transfer which is renamed when transfer is completed.
    ESFTPSTAT transferstatus;               // state of the transfer which has one of the above values (ESFTPSTAT)

    __int64 transferstarttime;              // time of start of the transfer
    wchar_t username[SHORT_BUFF_LEN];
    wchar_t password[SHORT_BUFF_LEN];
    wchar_t hostname[SHORT_BUFF_LEN];       // hostname of the sftp server
    wchar_t basedir[SHORT_BUFF_LEN];        // this base dir is the directory of public and private key structur ( NOT USED IN THIS VERSION)
    int port;                               //  port of the server;
    int verbosity;                          //  degree of verbosity of libssh
    __int64  filesize;                      //  total number of bytes to be transfered;
    DWORD  local_file_size_hiDWORD;         //  Bill Gates cannot accept the file size without twisting the programmers, so he accepts them in 2 separate words like this
    DWORD  local_file_size_lowDWORD;        //  these 2 DWORDs when connected together comprise a 64 bit file size.
    __int64 lfilesize;                          // local file size
    __int64 rfilesize;                          // remote file size
    __int64 transfered;                         // number of bytes already transfered
    __int64 initially_was_transferred;          // this is the number of bytes which was transferred before pause or interrupt of a transfer and used when resuming a transfer.
    bool pause;                                 // pause flag
    TTransStat stats;                           // statistics of the transfer
    HANDLE  localfilehandle;                    // windows uses handles to manipulate files. this is the handle to local file.
    int blocktransferdelay;

    ESSHERR CSFTPConnector::rwopen_existing_SFTPfile(char *fn);         // open a file on remote ( server ) read/write   for upload
    ESSHERR CSFTPConnector::rdopen_existing_SFTPfile(char *fn);         // open a file on remote ( server ) read only    for download
    ESSHERR createSFTPfile(char *fn);                                   // create a file on server;
    ESSHERR writeSFTPfile(char *block, size_t blocksize);               // write a block of data to the  open remote file
    ESSHERR readSFTPfile(char *block, size_t len, size_t *bytesread);   // read a block of data from the  open remote file
    ESSHERR readSFTPfile(char *block, __int64 len, DWORD *bytesread);
    ESSHERR closeSFTPfile();        // closes the remote file;
    ESSHERR openSFTPfile(char *fn);  // opens the remote file
    ESSHERR getSFTPfileinfo();          // gets information about the remote file


public:
    wstring errstring;      // the string describing last error 
    ESSHERR Err;                // error code of last error
    CSFTPConnector();           // default constructor;
    CSFTPConnector(wchar_t *dir, wchar_t *hn, int hostport, wchar_t *un, wchar_t *pass);  // constructor
    void setVerbosity(int v);       
    int  getVerbosity();
    ESSHERR InitSession();          // must be called befor doing any transfer
    ESSHERR ConnectSession();       // connnects to the  ssh server
    ESSHERR InitSFTP();     // must be called befor doing any transfer
    ESSHERR Makedir(char *newdir);
    ESSHERR testUploadFile(char *fn, char *block);          // do not use this , only for test purposes for myself
    ESSHERR SFTPput(char *lfn, char *rfn, size_t blocksize);            // Upload a file from start
    ESSHERR SFTPreput(char *lfn, char *rfn, size_t blocksize);          // checks for previouse interrupted transfer, then either continues the previouse transfer ( if there was any) or starts a new one (UPLOAD)
    ESSHERR SFTPrename(char *newname, char *oldname);                   // renames a remote file( must be closed)
    ESSHERR CSFTPConnector::SFTPdelete(char *remfile);                  // deletes a remote file
    TTransStat *getStatus();                                                // gets statistics of the transfer
    ESSHERR CSFTPConnector::SFTPget(char *lfn, char *rfn, size_t blocksize);    // Downloads a file from  sftp server
    ESSHERR CSFTPConnector::SFTPreget(char *lfn, char *rfn, size_t blocksize);  // checks for previouse interrupted transfer, then either continues the previouse transfer ( if there was any) or starts a new one (DOWNLOAD)
    void    CancelTransfer();
    void    PauseTransfer();
    void    setLogFile(FILE *logf);         // sets the log file, if not set stderr will be used. by default.
    void    CloseLocalFile();
    void    CloseRemoteFile();
    int GetSessionStatus();
    bool  IsConnected(); 
    void setBlockTransferDelay(int miliseconds);
    ESFTPSTAT getTransferStatus();
    ~CSFTPConnector();




} SFTPConnector, *pSFTPConnector ;



sftpstat CSFTPConnector::getTransferStatus()
{
    return  transferstatus;
}


void CSFTPConnector::setBlockTransferDelay(int miliseconds)
{
    blocktransferdelay = miliseconds;

}


bool CSFTPConnector::IsConnected()
{
    if (ssh_is_connected(session) == 1) return true;
    return false;
}



int CSFTPConnector::GetSessionStatus()
{
    return ssh_get_status(session);
}

void    CSFTPConnector::CloseLocalFile()
{
    CloseHandle(localfilehandle);
}


void    CSFTPConnector::CloseRemoteFile()
{
    sftp_close(file);
}



void    CSFTPConnector::setLogFile(FILE *logf)
{
    logfile = logf;
}


void    CSFTPConnector::CancelTransfer()
{
    transferstatus = ES_CANCELLED;

}
void    CSFTPConnector::PauseTransfer()
{
    transferstatus = ES_PAUSED;
    pause = true;
}

//----------------------------------------

// SFTPreger starts or resumes a download.
ESSHERR CSFTPConnector::SFTPreget(char *lfn, char *rfn, size_t blocksize)
{
    ESSHERR     result;
    int rc;
    BOOL  bresult;
    DWORD bytesread;
    DWORD byteswritten;
    filesize = 0;
    transfered = 0;
    initially_was_transferred = 0;
    lfilesize = rfilesize = 0;
    pause = false;
    transferstatus = ES_NONE;
    char *block;
    struct stat st;
    wchar_t temp[SHORT_BUFF_LEN];
    size_t tempsize;
    wstring wlfn;
    int loopcounter = 0;

    localfilename = lfn;
    filename = rfn;

    tempfilename = string(lfn) + ".sftp_temp";
    mbstowcs_s(&tempsize, temp, tempfilename.c_str(), SHORT_BUFF_LEN);

    localfilehandle = CreateFile(temp, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (localfilehandle == INVALID_HANDLE_VALUE)
    {
        transferstatus = ES_FAILED;
        errstring = L"Could not open local file:" + wstring(temp) +L" for read and write";
        Err = E_LOCAL_FILE_RDWR;
        return E_LOCAL_FILE_RDWR;
    }
    local_file_size_lowDWORD = GetFileSize(localfilehandle, &local_file_size_hiDWORD);
    lfilesize = (local_file_size_hiDWORD * 0x100000000) + local_file_size_lowDWORD;

    if (lfilesize < 0) {
        transferstatus = ES_FAILED;
        Err = E_LOCAL_FILE_NOTFOUND;
        errstring = L"Could not get size info for file:" + wstring(temp); 
        CloseLocalFile();
        return E_LOCAL_FILE_NOTFOUND;
    }

    transfered = lfilesize;
    initially_was_transferred = lfilesize;

    __int64 tempi64 = transfered & 0x00000000FFFFFFFF;
    DWORD dwlow = tempi64;
    tempi64 = (transfered  & 0x7FFFFFFF00000000);
    tempi64 = tempi64 >> 32;
    long  dwhi = tempi64;
    DWORD dwResult = SetFilePointer(localfilehandle, dwlow, &dwhi, FILE_BEGIN);
    if (dwResult == INVALID_SET_FILE_POINTER)
    {
        errstring = L"could not set file pointer for localfile" + wstring(temp);
        transferstatus = ES_FAILED; Err = result; 
        CloseLocalFile();
        return result;
    }

    block = (char*)malloc(blocksize + 1);
    if (block == NULL) {
        Err = E_MEM_ALLOC;
        transferstatus = ES_FAILED;
        errstring = L"Could not allocate memory for file block size";
        CloseLocalFile();
        return E_MEM_ALLOC;
    }

    result = rdopen_existing_SFTPfile((char *)rfn);

    if (result == E_OK){
        getSFTPfileinfo();
        filesize = rfilesize;       
    }
    else
    {
        Err = E_REMOTE_FILE_OPEN;
        transferstatus = ES_FAILED;
        errstring = L"Could not open remote file";
        CloseLocalFile();
        delete block;
        return E_REMOTE_FILE_OPEN;
    }


    rc=sftp_seek64(file, transfered);
    if (rc != SSH_OK)
    {
        Err = E_REMOTEFILE_SEEK;
        transferstatus = ES_FAILED;
        errstring = L"Could not set pointer for remote file";
        CloseRemoteFile();
        CloseLocalFile();
        delete block;
        return E_REMOTEFILE_SEEK;
    }

        transferstatus = ES_RESUMING;


    sftp_file_set_blocking(file);

    transferstarttime = time(NULL);
    transferstatus = ES_INPROGRESS;

    while (transferstatus != ES_FAILED && transferstatus != ES_PAUSED &&  transferstatus!=ES_CANCELLED  &&transferstatus != ES_DONE)
    {
        loopcounter++;

        result = readSFTPfile(block,blocksize, (size_t *) &bytesread);
        if (result != E_OK && result != E_SFTP_READ_EOF)
        {
            errstring = L"Error reading from remote sftp server file.";
            Err = result;
            transferstatus = ES_FAILED;
            CloseRemoteFile();
            CloseLocalFile();
            delete block;
            return result;
        }
        if (result == E_SFTP_READ_EOF)  transferstatus = ES_DONE;
        fprintf(logfile, "Read %d bytes from input file. Number of packets: %d , %llu from %llu bytes\n", bytesread, loopcounter, transfered, filesize);

        bresult = WriteFile(localfilehandle, (LPVOID)block, bytesread, &byteswritten, NULL);
        if (byteswritten < bytesread)
        {
            if (bresult == FALSE)
            {
                errstring = L"Error writing to local file.";
                Err = E_LOCAL_FILE_RDWR;
                transferstatus = ES_FAILED;
                CloseRemoteFile();
                CloseLocalFile();
                delete block;
                return E_LOCAL_FILE_RDWR;
            }
            else if (bytesread == 0)
            {
                errstring = L"Transfer done.";
                Err = E_OK;
                transferstatus = ES_DONE;
                continue;
            }
        }


        Err = E_OK;

        if (pause == true) transferstatus = ES_PAUSED;
        if (bresult == TRUE &&  bytesread == 0)
        {
            // at the end of the file
            transferstatus = ES_DONE;
        }
        Sleep(blocktransferdelay);
        if (loopcounter % 71 == 0)Sleep(7 * blocktransferdelay);
        if (loopcounter % 331 == 0)Sleep(77 * blocktransferdelay);
        if (loopcounter % 3331 == 0)Sleep(777 * blocktransferdelay);

    }
    result = closeSFTPfile();
    CloseHandle(localfilehandle);
    Sleep(1000);

    if (transferstatus == ES_DONE)
    {
        wchar_t temp2[SHORT_BUFF_LEN];
        mbstowcs_s(&tempsize, temp2, lfn, SHORT_BUFF_LEN);
        bresult = MoveFile(temp, temp2);
        if (bresult != TRUE)
        {
            Err = E_RENAME_LOCAL_FILE;
            errstring = L"Could not rename local file: " + wstring(temp);
            transferstatus = ES_FAILED;
            delete block;
            return E_RENAME_LOCAL_FILE;
        }
    }

    if (transferstatus == ES_CANCELLED)
    {
        wchar_t temp2[SHORT_BUFF_LEN];
        mbstowcs_s(&tempsize, temp2, lfn, SHORT_BUFF_LEN);
        bresult = DeleteFile(temp);
        if (bresult != TRUE)
        {
            Err = E_LOCAL_DELETE_FILE;
            errstring = L"Could not rename local file: " + wstring(temp);
            transferstatus = ES_FAILED;
            delete block;
            return E_LOCAL_DELETE_FILE;
        }
    }

    delete block;
    return result;
}




//---------------------------------------



TTransStat * CSFTPConnector::getStatus()
{
    stats.seconds_elapsed = time(NULL); 
    stats.seconds_elapsed -= transferstarttime;
    stats.averagebps = ((transfered- initially_was_transferred) * 8) / stats.seconds_elapsed;
    if (filesize > 0) {
        stats.percent = (transfered *100)/ filesize;
        stats.seconds_remained = ((filesize - transfered) * 8) / stats.averagebps;
    }
    else
    {
        stats.percent = -1;
        stats.seconds_remained = -1;
    }
    stats.total_size = filesize;
    stats.transferstate = transferstatus;
    stats.remote_file_name = filename;
    stats.local_file_name = localfilename;
    stats.transferred = transfered;
    stats.initially_transferred = initially_was_transferred;


    return &stats;
}


ESSHERR CSFTPConnector::SFTPrename(char *newname, char *oldname)
{

    int rc=sftp_rename(sftp, oldname, newname);
    if (rc !=SSH_OK){
        return E_RENAME_ERR;
    }

    return E_OK;
}



ESSHERR CSFTPConnector::SFTPdelete(char *remfile)
{

    int rc = sftp_unlink(sftp,remfile);
    if (rc != SSH_OK){
        return E_DELETE_ERR;
    }

    return E_OK;
}

// SFTPreput
ESSHERR CSFTPConnector::SFTPreput(char *lfn, char *rfn, size_t blocksize)
{
    ESSHERR     result;
    BOOL  bresult;
    DWORD bytesread;
    filesize = 0;
    transfered = 0;

    pause = false;
    transferstatus = ES_NONE;
    char *block;
    struct stat st;
    wchar_t temp[SHORT_BUFF_LEN];
    size_t tempsize;
    wstring wlfn;
    int loopcounter = 0;

    localfilename = lfn;
    //wlfn = wstring(lfn);
    //localfile = fopen(lfn, L"r");
    filename = rfn;
    mbstowcs_s(&tempsize, temp, lfn, SHORT_BUFF_LEN);

    //filesize = getFileSize(localfilename);

    /*if(filesize < 0) {
    transferstatus = ES_FAILED;
    Err = E_LOCAL_FILE_NOTFOUND;
    return E_LOCAL_FILE_NOTFOUND;
    }*/

    localfilehandle = CreateFile(temp, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (localfilehandle == INVALID_HANDLE_VALUE)
    {
        transferstatus = ES_FAILED;
        Err = E_LOCAL_FILE_NOTFOUND;
        return E_LOCAL_FILE_NOTFOUND;
    }
    local_file_size_lowDWORD = GetFileSize(localfilehandle, &local_file_size_hiDWORD);
    filesize = (local_file_size_hiDWORD * 0x100000000) + local_file_size_lowDWORD;

    if (filesize < 0) {
        transferstatus = ES_FAILED;
        Err = E_LOCAL_FILE_NOTFOUND;
        CloseLocalFile();
        return E_LOCAL_FILE_NOTFOUND;
    }

    block = (char*)malloc(blocksize + 1);
    if (block == NULL) {
        Err = E_MEM_ALLOC;
        transferstatus = ES_FAILED;
        errstring = L"Could not allocate memory for file block size";
        CloseLocalFile();
        return E_MEM_ALLOC;
    }


    tempfilename = string(rfn) + ".sftp_temp";

    result = rwopen_existing_SFTPfile((char *)tempfilename.c_str());
    if (result == E_OK){
        getSFTPfileinfo();
        sftp_seek64(file, rfilesize);
        __int64 tempi64 = rfilesize & 0x00000000FFFFFFFF;
        DWORD dwlow = tempi64;
        tempi64 = (rfilesize & 0x7FFFFFFF00000000);
        tempi64 = tempi64 >> 32;
        long  dwhi = tempi64;
        DWORD dwResult=SetFilePointer(localfilehandle, dwlow,&dwhi , FILE_BEGIN);
        if (dwResult == INVALID_SET_FILE_POINTER)
        {
            transferstatus = ES_FAILED; Err = result;  return result;
        }
        transferstatus = ES_RESUMING;
        transfered = rfilesize;
        initially_was_transferred = rfilesize;

    }
    else{
        result = createSFTPfile((char *)tempfilename.c_str());
        transferstatus = ES_STARTING;
        rfilesize = 0;
        initially_was_transferred = 0;
        if (result != E_OK)  {
            transferstatus = ES_FAILED; 
            Err = result;
            CloseLocalFile();
            return result;
        }
        }
        sftp_file_set_blocking(file);
        transferstarttime = time(NULL);
        transferstatus = ES_INPROGRESS;

    while (transferstatus != ES_FAILED && transferstatus != ES_PAUSED && transferstatus != ES_DONE)
    {
        loopcounter++;
        bresult = ReadFile(localfilehandle, (LPVOID)block, blocksize, &bytesread, NULL);
        fprintf(logfile, "Read %d bytes from input file. Number of packets: %d , %llu from %llu bytes\n", bytesread, loopcounter, transfered, filesize);
        if (bytesread < blocksize)
        {
            if (bresult == FALSE)
            {
                errstring = L"Error reading from local file.";
                Err = E_LOCAL_FILE_READ;
                transferstatus = ES_FAILED;
                CloseRemoteFile();
                CloseLocalFile();
                return E_LOCAL_FILE_READ;
            }
            else if (bytesread == 0)
            {
                errstring = L"Transfer done.";
                Err = E_OK;
                transferstatus = ES_DONE;
                continue;
            }
        }

        result = writeSFTPfile(block, bytesread);
        if (result != E_OK && bytesread>0 )
        {
            errstring = L"Error transmitting to remote sftp server file.";
            Err = result;
            transferstatus = ES_FAILED;
            CloseRemoteFile();
            CloseLocalFile();
            return result;
        }


        Err = E_OK;
        //transfered = transfered + bytesread;
        if (pause == true) transferstatus = ES_PAUSED;
        if (bresult == TRUE &&  bytesread == 0)
        {
            // at the end of the file
            transferstatus = ES_DONE;
        }
        Sleep(blocktransferdelay);
        if (loopcounter % 71 == 0)Sleep(7 * blocktransferdelay);
        if (loopcounter % 331 == 0)Sleep(77 * blocktransferdelay);
        if (loopcounter % 3331 == 0)Sleep(777 * blocktransferdelay);

    }

    CloseRemoteFile();
    CloseLocalFile();
    Sleep(1000);

    if (transferstatus == ES_CANCELLED)
    {
        result = SFTPdelete((char *)tempfilename.c_str());
        if (bresult != E_OK)
        {
            Err = E_DELETE_ERR;
            errstring = L"Could not delete remote file.";
            transferstatus = ES_FAILED;
            return E_DELETE_ERR;
        }
    }
    if (transferstatus == ES_DONE) result = SFTPrename(rfn, (char *)tempfilename.c_str());
    delete block;
    return result;
}




ESSHERR CSFTPConnector::getSFTPfileinfo()
{
    sftp_attributes fileinf = sftp_fstat(file);

    if (fileinf == NULL){
        return E_GET_FILEINF;
    }

    rfilesize = fileinf->size;

    sftp_attributes_free(fileinf);
    return E_OK;
}

ESSHERR CSFTPConnector::closeSFTPfile()
{
    int rc = sftp_close(file);
    if (rc != SSH_OK)
    {
        fprintf(logfile, "Can't close the written file: %s\n",
            ssh_get_error(session));
        return E_FILE_CLOSE;
    }
    return E_OK;
}




ESSHERR CSFTPConnector::writeSFTPfile(char *block, size_t blocksize)
{
    size_t nwritten = sftp_write(file, block, blocksize);
    if (nwritten != blocksize)
    {
        fprintf(logfile, "Can't write data to file: %s\n",
            ssh_get_error(session));
        //sftp_close(file);
        transfered = transfered + nwritten;
        return E_WRITE_ERR;
    }

    transfered = transfered + nwritten;
    return E_OK;
}
ESSHERR CSFTPConnector::readSFTPfile(char *block, __int64 len, DWORD *bytesread)
{
    DWORD readbytes;
    *bytesread = 0;
    if (len <= 0) return E_INVALID_PARAMS;
    if (bytesread == NULL || block == NULL) return E_INVALID_PARAMS;

    readbytes = sftp_read(file, block, len);
    if (readbytes < 0)
    {
        fprintf(logfile, "Can't read  from  remote file: %s  %s\n", filename.c_str(), ssh_get_error(session));
        *bytesread = 0;
        return E_SFTP_READ_ERR;
    }


    if (readbytes <  len)
    {
        *bytesread = readbytes;
        return E_SFTP_READ_EOF;
    }


    *bytesread = readbytes;
    transfered = transfered + readbytes;

    return E_OK;

}


ESSHERR CSFTPConnector::createSFTPfile(char *fn)
{

    int access_type = O_CREAT | O_RDWR | O_APPEND;
    int rc, nwritten;

    filename = string(fn);
    file = sftp_open(sftp, fn,access_type,  S_IREAD | S_IWRITE);
    if (file == NULL)
    {
        fprintf(logfile, "Can't open file for writing: %s\n",
            ssh_get_error(session));
        return E_FILEOPEN_WRITE;
    }
    return E_OK;
}





ESSHERR CSFTPConnector::openSFTPfile(char *fn)
{
    int access_type = O_RDONLY;
    int rc, nwritten;

    filename = string(fn);
    file = sftp_open(sftp, fn,
        access_type, S_IWRITE);
    if (file == NULL)
    {
        fprintf(logfile, "Can't open file for writing: %s\n",
            ssh_get_error(session));
        return E_FILE_OPEN_READ;
    }
    return E_OK;

}

ESSHERR CSFTPConnector::Makedir(char *newdir)
{
    int rc;
    rc = sftp_mkdir(sftp, newdir, S_IFDIR);
    if (rc != SSH_OK)
    {
        if (sftp_get_error(sftp) != SSH_FX_FILE_ALREADY_EXISTS)
        {
            fprintf(logfile, "Can't create directory: %s\n",
                ssh_get_error(session));
            return E_CREATE_DIR;
        }
    }

        return E_OK;
}




SFTPConnector::CSFTPConnector()
{
    //libssh2_init(0);
    session = ssh_new();
    if (session == NULL)
    {
        Err = E_SESSION_ALOC;
        errstring = L"Could not allocate a session.";

    }
    wcscpy(hostname, L"localhost" );
    wcscpy(username, L"User");
    wcscpy(password, L"Password");
    wcscpy(basedir, L".\\");
    port = 22;
    verbosity = SSH_LOG_RARE;
    filesize = 0;
    transfered = 0;

    pause = false;
    transferstatus = ES_NONE;
    logfile = stderr;
    blocktransferdelay = INITIALBLOCKTRANSDELAY;

}




CSFTPConnector::CSFTPConnector(wchar_t *dir, wchar_t *hn, int hostport, wchar_t *un, wchar_t *pass)
{

    //libssh2_init(0);
    session = ssh_new();

    if (session == NULL)
    {
        Err = E_SESSION_ALOC;
        errstring = L"Could not allocate a session.";

    }
    wcscpy(hostname, hn);
    wcscpy(username, un);
    wcscpy(password, pass);
    wcscpy(basedir, dir);
    port = hostport;
    verbosity = SSH_LOG_RARE;
     filesize=0;
     transfered=0;

     pause=false;
     transferstatus = ES_NONE;
     logfile = stderr;
     blocktransferdelay = INITIALBLOCKTRANSDELAY;

}


ESSHERR  CSFTPConnector::InitSFTP()
{
    int rc;
    sftp= sftp_new(session);
    if (session == NULL)
    {
        Err = E_SFTP_ALLOC;
        errstring = L"Could not allocate a sftp session.";

    }

    rc = sftp_init(sftp);
    if (rc != SSH_OK)
    {
        fprintf(logfile, "Error initializing SFTP session: %s.\n",
            sftp_get_error(sftp));
        sftp_free(sftp);
        return E_INIT_SFTP;
    }


    return E_OK;
}


ESSHERR  CSFTPConnector::ConnectSession()
{
    char temp[SHORT_BUFF_LEN];
    size_t n_of_chars;
    wcstombs_s(&n_of_chars, temp, SHORT_BUFF_LEN, (const wchar_t *)password, SHORT_BUFF_LEN);
    int ir;

    ir=ssh_connect(session);
    if (ir != SSH_OK){
        errstring = L"Could not connect the ssh session.";
        return E_SSH_CONNECT_ERR;
    }

    ir=ssh_userauth_password(session, NULL, temp);
    if (ir != SSH_OK){
        errstring = L"Could not authenticate with the ssh server.\r\n";
        return E_AUTHENTICATE;
    }
    return E_OK;
}


ESSHERR  CSFTPConnector::InitSession()
{
    char temp[SHORT_BUFF_LEN];
    size_t n_of_chars;
    wcstombs_s(&n_of_chars, temp,SHORT_BUFF_LEN, (const wchar_t *) hostname, SHORT_BUFF_LEN);
    ssh_options_set(session, SSH_OPTIONS_HOST,temp);
    ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
    ssh_options_set(session, SSH_OPTIONS_PORT, &port);
    wcstombs_s(&n_of_chars, temp, SHORT_BUFF_LEN, (const wchar_t *)username, SHORT_BUFF_LEN);
    ssh_options_set(session, SSH_OPTIONS_USER,temp);
    wcstombs_s(&n_of_chars, temp, SHORT_BUFF_LEN, (const wchar_t *)basedir, SHORT_BUFF_LEN);
    ssh_options_set(session, SSH_OPTIONS_SSH_DIR, temp);

    return E_OK;
}


void  CSFTPConnector::setVerbosity(int v)
{
    verbosity = v;
}


int  CSFTPConnector::getVerbosity()
{
    return verbosity;
}
于 2014-09-24T00:33:12.047 回答