Linux下使用libcurl实现FTP单个文件或者压缩包上传下载功能
一、关于FTP
参考:在WIN10上搭建Ftp服务器
二、FTP上传
该FTP上传代码为官网上的demo例程代码,若要为己所用,只需将宏定义修改并准备一个要上传的文件即可。当然,该函数只能上传一个文件或者压缩包至FTP服务器,若要上传多个文件,可以在此例程上进行修改。
#include <stdio.h>
#include <string.h>
#include <curl/curl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#ifdef WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
#define LOCAL_FILE "/mnt/hgfs/VMWARE/test/8-curl/1206.rar" //要上传的文件
#define UPLOAD_FILE_AS "while-uploading.txt"
#define REMOTE_URL "ftp://192.168.31.175/" UPLOAD_FILE_AS //FTP服务器地址
#define RENAME_FILE_TO "1206.rar"//最终写入到这个文件名中
static 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, stream);
nread = (curl_off_t)retcode;
fprintf(stderr, " We read %" CURL_FORMAT_CURL_OFF_T
" bytes from file\n", nread);
return retcode;
}
int main(void)
{
CURL *curl;
CURLcode res;
FILE *hd_src;
struct stat file_info;
curl_off_t fsize;
struct curl_slist *headerlist = NULL;
static const char buf_1 [] = "RNFR " UPLOAD_FILE_AS;
static const char buf_2 [] = "RNTO " RENAME_FILE_TO;
/* 获得上传文件的大小 */
if(stat(LOCAL_FILE, &file_info)) {
printf("Couldn't open '%s': %s\n", LOCAL_FILE, strerror(errno));
return 1;
}
fsize = (curl_off_t)file_info.st_size;
printf("Local file size: %" CURL_FORMAT_CURL_OFF_T " bytes.\n", fsize);
/* 获得FILE类型变量 */
hd_src = fopen(LOCAL_FILE, "rb");
/* 初始化 */
curl_global_init(CURL_GLOBAL_ALL);
/* 获得curl操作符 */
curl = curl_easy_init();
if(curl) {
/*建立一个传递给libcurl的命令列表 */
headerlist = curl_slist_append(headerlist, buf_1);
headerlist = curl_slist_append(headerlist, buf_2);
/* 使用curl提供的Read功能 */
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
/* 上传使能 */
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
/* 设置特定目标 */
curl_easy_setopt(curl, CURLOPT_URL, REMOTE_URL);
/* 传递最后一个FTP命令以在传输后运行 */
curl_easy_setopt(curl, CURLOPT_POSTQUOTE, headerlist);
/*指定上传文件 */
curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);
/*设置要上传的文件的大小(可选) */
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
(curl_off_t)fsize);
/* 运行 */
res = curl_easy_perform(curl);
/* 容错处理 */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* 清除FTP命令列表 */
curl_slist_free_all(headerlist);
/*释放所有curl资源 */
curl_easy_cleanup(curl);
}
fclose(hd_src); /*关闭本地文件 */
/*释放所有curl资源 */
curl_global_cleanup();
return 0;
}
保存代码,文件名命名为“ftpupload.c”,并在/mnt/hgfs/VMWARE/test/8-curl文件夹中准备“1206.rar”文件(即代码中指定的要上传的文件名),使用gcc编译,编译指令:
gcc -o ftpupload ftpupload.c -lcurl
执行结果:
?上传前的代码:
上传到FTP服务器之后:
至此,上传功能完成。
?三、FTP下载
同样,该FTP下载代码为官网上的demo例程代码,若要为己所用,只需将宏定义修改并指定一个要下载的文件即可。当然,该函数只能下载一个文件或者压缩包至FTP客户端,若要下载多个文件,可以在此例程上进行修改。
#include <stdio.h>
#include <curl/curl.h>
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; /* failure, can't open file to write */
}
return fwrite(buffer, size, nmemb, out->stream);
}
int main(void)
{
CURL *curl;
CURLcode res;
struct FtpFile ftpfile = {
"/mnt/hgfs/VMWARE/test/8-curl/1208.rar", /* 若FTP下载成功,名命下载后的文件为"curl.txt" */
NULL
};
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL,
"ftp://192.168.31.175/1208.rar");//下载指定的文件
/* 定义回调函数,以便在需要写入数据时进行调用 */
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
/*设置一个指向我们的结构的指针传递给回调函数*/
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
/* 打开完整的协议/调试输出*/
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);
}
}
if(ftpfile.stream)
fclose(ftpfile.stream); /* 关闭本地文件 */
/*释放所有curl资源*/
curl_global_cleanup();
return 0;
}
使用gcc编译,编译指令:
gcc -o ftpDown ftpDown.c -lcurl
执行结果:
?下载之前,放在FTP服务器中时:
下载之后,放在本地文件中中时:
|