linux curl t上传文件,Linux下使用libcurl实现FTP单个文件上传下载功能

本文介绍libcurl库的功能及使用方法,并通过实例演示FTP上传与下载功能的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.前言

1.1声明

文章中的文字可能存在语法错语以及标点错误,请谅解;

如果在文章中发现代码错误或其它问题请告知,感谢!

2.关于libcurl

2.1简介

libcurl是一个提供数据传输功能的函数库,主要功能就是通过其使用不同的协议连接不同类型的服务器。当前libcurl支持的协议主要有http, https, ftp, gopher, telnet, dict, file, 和ldap等协议和各种SSL安全认证。

在基于libcurl的程序里,使用libcurl提供的库函数完成特定任务。开发者在启动传输任务之前写好回调函数以及设置各类参数,当满足条件时,libcurl调用回调函数实现功能任务。

当然,官网上有其详细的介绍:

https://curl.haxx.se/libcurl/features.html

2.2libcurl功能实现逻辑

一般情况下,libcurl的实现逻辑如下:

09e13a604a5210a1a3d189490d35c8e1.png

2.3主要函数

1.CURLcode curl_global_init(long falgs);

该函数在程序中只能够使用一次,若这个函数在curl_easy_init函数调用时还没调用,它讲由libcurl库自动完成。该函数需要用到的参数如下:

CURL_GLOBAL_ALL:初始化所有可能的调用

CURL_GLOBAL_SSL:初始化支持安全套接字的调用

CURL_GLOBAL_WIN32:初始化WIN32套接字库

CURL_GLOBAL_NOTHING:没有额外的初始化要求

2.CURL* curl_easy_init();

用来初始化一个curl指针。在该指针调用结束后需要使用curl_easy_cleanup函数清理。

通常来说当使用curl_easy_init()产生一个curl指针后,基本上只会被curl库中easy系列函数中调用,可以参见下例理解。

3.CURLcode curl_easy_setopt(CURL* handle,CURLoption option,parameter);

用来告诉curl库程序需要该库做何等行为。CURL* handle为操作符,CURLoption option代表各类选项,option parameter 这个参数既可以是个函数的指针,也可以是某个对象的指针,也可以是个long型的变量.它用什么这取决于第二个参数.。

4.CURLcode curl_easy_perform(CURL* handle);

设置好curl_easy_setopt工作方式后,调用该函数开始运行会话。CURL* handle为操作符。

5.void curl_easy_cleanup(CURL*handle);

用来结束一个libcurl会话,与curl_easy_init配合使用。CURL* handle为操作符。

6.void curl_global_cleanup(void);

用该函数结束所有有关libcurl使用,类似于close()的函数。

要是对libcur库中所有函数进行一个详细的了解,可以参考libcurl官网:

https://curl.haxx.se/libcurl/c/

3.FTP功能实现

3.1linux下编译安装libcurl

1.首先在终端中输入指令:git clone https://github.com/curl/curl.git ,下载libcurl源码:

3164c924b09851088087c4af3d5610b8.png

2.tar解压后,进入curl工程目录输入指令:./buidconf,产生configure脚本:

ef3ece6786210f736db60bf82b99c4c3.png

注意:在输入指令后可能会出现“buildconf: autoconf not found.”错误,此时输入指令:apt-get install autoconf安装必要的文件,然后再次输入./buidconf指令即可。

3.输入指令: ./configure –enable-debug 执行configure脚本:

dd5fe0a45bee5865533e77ec8a04145a.png

4.输入指令:make

ad1f78a96850f07aac0762a55cf215a0.png

5.输入指令:make install,完成安装

b0aeddf7cbd716899c84acb147c838af.png

3.2代码实现

我在win10上搭建了一个FTP服务器作为测试用,搭建步骤可以参考网上例程,该服务器网址在搭建的时候设置为:ftp://192.168.1.116/ ,里面预先传送了几个文件,下面的FTP上传下载功能将在这个FTP服务器进行。

c5b2ec82d31ada2c9dfd0317de8e2e76.png

接着将Linux主机和FTP服务器连接到同一个局域网,然后互ping一下检查是否能够互相通信成功。

3.2.1FTP上传

该FTP上传代码为官网上的demo例程代码,若要为己所用,只需将宏定义修改并准备一个要上传的文件即可。当然,该函数只能上传一个文件至FTP服务器,若要上传多个文件,可以在此例程上进行修改。

#include

#include

#include

#include

#include

#include

#include

#ifdef WIN32

#include

#else

#include

#endif

#define LOCAL_FILE "/home/dlri/Desktop/uploadthis.txt" //要上传的文件

#define UPLOAD_FILE_AS "while-uploading.txt"

#define REMOTE_URL "ftp://192.168.1.116/" UPLOAD_FILE_AS //FTP服务器地址

#define RENAME_FILE_TO "renamed-and-fine.txt"

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;

}

保存代码,文件名命名为“ftptest.c”,并在/home/dlri/Desktop文件夹中准备“uploadthis.txt”文件(即代码中指定的要上传的文件名),使用gcc编译,编译指令:gcc -o ftptest ftptest.c -lcurl

9b0e2516a9189a219ad36bd372161932.png

编译成功后,运行:

d2f9ae48dfabc1f1b8278c7dc1de09c6.png

此时查看FTP服务器:

d48a1f41f100bfe9af7b0adba363a6da.png

打开文件,对比Linux中的“uploadthis.txt”文件:

16a053df8e79a28a5d45e8bb313e552d.png

29e89bb5cda5cbae5d52294d0f829f04.png

上传功能完成。

3.2.2FTP下载

同样,该FTP下载代码为官网上的demo例程代码,若要为己所用,只需将宏定义修改并指定一个要下载的文件即可。当然,该函数只能下载一个文件至FTP客户端,若要下载多个文件,可以在此例程上进行修改。

#include

#include

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 = {

"curl.txt", /* 若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.1.116/a.txt");//下载指定的文件

/* 定义回调函数,以便在需要写入数据时进行调用 */

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

fa719c5ebd1f0470a60af6247a460b1f.png

编译成功后,运行:

e18f5ae11b05bff85ae7cd9bc8430ef5.png

对比下载的文件和FTP上的文件:

e3ba335b912c580fb775044afa14cbed.png

8bb2db2358b101739561f32e908bb196.png

以上。

参考文档:

1.https://blog.youkuaiyun.com/sever2012/article/details/7076248

2.https://curl.haxx.se/libcurl/c/ftpupload.html

3.https://curl.haxx.se/libcurl/c/ftpget.html

4.http://www.360doc.com/content/16/0616/11/33377968_568201213.shtml

5.https://jingyan.baidu.com/article/91f5db1b1922ba1c7e05e350.html

6.https://blog.youkuaiyun.com/wangqing_12345/article/details/52233067

7.https://baike.baidu.com/item/libcurl/5256898?fr=aladdin

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值