Linux系统下SFTP上传下载实现

╄→尐↘猪︶ㄣ 提交于 2019-12-17 23:24:58

1.功能介绍

1.1 sftp(安全文件传送协议),从字面意思看,就是我们常用的文件上传下载协议,实现文件的上传下载功能。

2.如实使用sftp

2.1 网上也有很多封装好的库,也很好用,可以跨平台;今天我分享的是基于Linux系统编程的sftp,不需要下载任何库,拿去直接可用,也写了相应的测试程序可参考。

3.SFTP代码

#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>//sftp使用Linux系统里的头文件

#undef DISABLE_SSH_AGENT

size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream) //上传回调函数
{
    curl_off_t nread;
    size_t retcode = fread(ptr, size, nmemb, (FILE*)(stream));
    nread = (curl_off_t)retcode;
    return retcode;
}

int SftpUpload(const char *pUrlKey, const char *pPathFile, const char *pSftpUrl)
{
	CURL *curl;
	CURLcode res;	

	if ((NULL == pUrlKey) || (NULL == pPathFile) || (NULL == pSftpUrl))
	{
		return -1;
	}
	
	FILE* pSendFile = fopen(pPathFile, "rb");
	fseek(pSendFile, 0L, SEEK_END);
	size_t iFileSize = ftell(pSendFile);
	fseek(pSendFile, 0L, SEEK_SET);
   

	curl_global_init(CURL_GLOBAL_DEFAULT);

	curl = curl_easy_init();
	if(curl) {
	curl_easy_setopt(curl, CURLOPT_URL,	pSftpUrl);
	curl_easy_setopt(curl, CURLOPT_USERPWD,pUrlKey);  
	curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
	curl_easy_setopt(curl, CURLOPT_READDATA, pSendFile);
	curl_easy_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS, 0);
	curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
	curl_easy_setopt(curl, CURLOPT_INFILESIZE, iFileSize);

#ifndef DISABLE_SSH_AGENT
		curl_easy_setopt(curl, CURLOPT_SSH_AUTH_TYPES, CURLSSH_AUTH_PASSWORD);
#endif
		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
	res = curl_easy_perform(curl);

	curl_easy_cleanup(curl);

	if(CURLE_OK != res) 
	{
		fprintf(stderr, "curl told us %d\n", res);
	}
  }
	fclose(pSendFile);
	curl_global_cleanup();
	
	return 0;
}

struct FtpFile {
  const char *filename;
  FILE *stream;
};

static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) //下载回调函数
{
  struct FtpFile *out = (struct FtpFile *)stream;
  if(out && !out->stream) {
    /* 打开文件以进行写操作 */ 
    out->stream = fopen(out->filename, "wb");
    if(!out->stream)
      return -1;   /* 打开文件失败 */ 
  }
  return fwrite(buffer, size, nmemb, out->stream);
}

int SftpDownload(const char *pUrlKey,const char *pPathFile, const char *pSftpUrl)
{
	CURL *curl;
	CURLcode res;
  	curl_global_init(CURL_GLOBAL_DEFAULT);

  	curl = curl_easy_init();
  	if(curl) {
	curl_easy_setopt(curl, CURLOPT_USERPWD,pUrlKey);  
    curl_easy_setopt(curl, CURLOPT_URL,pSftpUrl);	//下载指定的文件
    /* 定义回调函数,以便在需要写入数据时进行调用 */ 
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
    /*设置一个指向我们的结构的指针传递给回调函数*/ 
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, pPathFile);

    /* 打开完整的协议/调试输出*/ 
    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

    res = curl_easy_perform(curl);

    /* 释放所有curl资源*/ 
    curl_easy_cleanup(curl);

    if(CURLE_OK != res) {
      /*容错处理 */ 
      fprintf(stderr, "curl told us %d\n", res);
    }
  }

 /*释放所有curl资源*/
  curl_global_cleanup();
	
}


void SftpDownloadTest()//下载测试程序
{
  	char tmp[256]="/root/workspace/88888.pl";//下载下来的文件保存在当前程序所在服务器的绝对路径,下载下来后命名为88888.pl
  	struct FtpFile ftpfile ;
  	ftpfile.filename=tmp;
  	ftpfile.stream=NULL;
  	const char* urlkey = "root:1"; //远程下载地址服务器的用户名密码
  	const char* pSftpUrl="sftp://10.20.1.177:22/home/2.tt";//具体的远程下载地址,从10.20.1.177服务器上下载2.tt这个文件
	SftpDownload(urlkey,(const char *)&ftpfile,pSftpUrl);
	return 0;
}

void SftpUploadTest()//上传测试程序
{
	const char filename[]="/root/workspace/test.c";//当前程序所在服务器要上传文件的绝对路径,test.c为要上传的文件
  	const char* urlkey = "root:1"; //上传地址服务器的用户名密码
  	const char* pSftpUrl="sftp://10.20.1.177:22/home/mytest.c";//具体上传的目的地址,将test.c文件上传到10.20.1.177服务器,命名为mytest.c
	SftpUpload(urlkey,filename,pSftpUrl);
}

int main()
{
	SftpDownloadTest();
	SftpUploadTest();
	return 0;
}

4.注意事项

4.1 源码看不懂没关系,知道怎么用就行,重点在测试程序。
4.2 编译时要加 -lcurl ,例如:gcc -o sftp sftp.c -lcurl,即可生成可执行程序sftp。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!