使用libcurl库上传sftp服务器,上传.txt文件成功,且sftp收到的.txt文件大小正常。上传.xlsx文件时也提示成功,sftp上也有收到文件,但文件大小变成1k了,不是实际大小,excel不能打开。(上传.rar文件也变成1k大小),不知道这是为什么,代码如下,请帮忙查看一下。
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;
}
size_t CTest02Dlg::upload(const char * user,const char * passwd,const char * url, const char * path)
{
curl_global_init(CURL_GLOBAL_DEFAULT);
int nRet(-1);
CURL *curl;
CURLcode res;
//struct curl_slist *headerlist = NULL;
std::string s1(user);
std::string s2(passwd);
std::string s3 = s1;
s3.append(":");
s3.append(s2);
system("ls write_file");
FILE* pSendFile = fopen(path,"r");
if(pSendFile == NULL)
{
printf("open failed\n");
return 1;
}
printf("------------\n");
fseek(pSendFile, 0L, SEEK_END);
printf("------------\n");
size_t iFileSize = ftell(pSendFile);
printf("------------\n");
fseek(pSendFile, 0L, SEEK_SET);
printf("begin easy_init\n");
curl = curl_easy_init();
printf("curl_easy_init success\n");
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL,url);
curl_easy_setopt(curl, CURLOPT_USERPWD,s3.c_str());
curl_easy_setopt(curl, CURLOPT_PROTOCOLS, CURLPROTO_SFTP);//
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);
printf("curl_easy_setopt success");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if(CURLE_OK != res)
{
nRet = 2;
fprintf(stdout, "curl told us %d\n", res);
}
else
{
nRet = 0;
}
}
fclose(pSendFile);
curl_global_cleanup();
return nRet;
}
void CTest02Dlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
int nRet = upload("sftpuser","123","sftp://192.168.2.15:22/test/(2023-05-1608_48_00).xlsx","D:\test\(2023-05-1608_48_00).xlsx");
}
来自NewBing和LP的编写:
你的代码看起来是正确的,但是有一些可能的原因会导致你的问题,要进一步进行排查。这里有一些可能的问题:
文件打开方式:你打开待上传文件时使用的是 "r" 模式,这个模式是用于读取文本文件的。但是 .xlsx 和 .rar 文件是二进制文件,你应该用 "rb" 模式打开文件。试修改你的代码,用 "rb" 模式打开文件:
FILE* pSendFile = fopen(path,"rb");
libcurl版本问题:你的libcurl库版本可能存在问题,有可能是版本过旧或者与你的程序存在不兼容的问题。你可以尝试更新到最新版本的libcurl库,或者尝试使用其他版本的libcurl库看看问题是否仍然存在。
服务器问题:服务器可能存在某些问题,导致无法正确处理上传的文件。你可以尝试更换服务器,或者联系服务器的管理员,看看是否存在可以解决的问题。
文件权限问题:在上传文件前,检查你是否有足够的权限来读取这些文件。如果没有,那么可能会导致文件大小不正确的问题。
这些都是可能导致你问题的原因,你可以尝试根据这些信息进行进一步的排查。如果问题仍然存在,那么可能需要进行更深入的调查。
没有使用“rb”模式以二进制方式打开文件。因此,在读取文件大小时将其视为文本文件,导致文件大小不正确。
您可以尝试使用“rb”(read binary)模式打开要上传的文件,以确保正确读取文件的大小:
FILE* pSendFile = fopen(path,"rb");
另外,由于二进制文件可能包含二进制数据,因此建议使用CURLPROTO_SFTP选项来指定协议。
curl_easy_setopt(curl, CURLOPT_PROTOCOLS, CURLPROTO_SFTP);
文件上传要以二进制的方式打开
FILE * file = fopen(imagePath, "rb");
另外在发送的时候需要指定文件的大小 fsize,这样服务器端就知道需要接收多少字节了
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, fsize);
根据提供的参考资料中的代码,无法直接得知链接中使用的是哪个版本的 libcurl 库。但是根据参考资料中的介绍,libcurl 是一个高可移植性、功能丰富的通信库,可以支持所有的应用层协议,适配兼容性非常好,基于 C 接口可以很容易写出各种语言的封装。因此,可以通过升级或更改 libcurl 库版本,在保证基本功能的前提下尽可能减少发生异常或警告信息的概率。
至于代码中的文件大小限制或其他限制,可以根据需求设置相应的参数。例如,可以使用 curl_easy_setopt 函数设置 CURLOPT_POSTFIELDSIZE_LARGE 选项,用于限制可以发送的最大文件大小。文件上传时的异常或警告信息可能与应用场景和具体实现有关,需要根据实际情况进一步分析调整。
以下是一个设置 CURLOPT_POSTFIELDSIZE_LARGE 的示例代码:
// 设置可以发送的最大文件大小
const int64_t kMaxFileSize = 1024 * 1024 * 50; // 50 MB
// ...
// 设置 CURLOPT_POSTFIELDSIZE_LARGE 选项
if (file_size > kMaxFileSize) {
curl_easy_setopt(curl_, CURLOPT_POSTFIELDSIZE_LARGE, 0L);
curl_easy_setopt(curl_, CURLOPT_FLAGS, (void*)(unsigned long)1); // 设置标志位
} else {
curl_easy_setopt(curl_, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)file_size);
}
// ...
当需要上传的文件大小超过 kMaxFileSize 时,将 CURLOPT_POSTFIELDSIZE_LARGE 设置为 0,代表取消发送;同时设置一个标志位以便在回调函数中提示错误。否则,将文件大小设置为 CURLOPT_POSTFIELDSIZE_LARGE,可以正常上传文件。需要注意的是,libcurl 库在实际应用中,除了基本的 CURLOPT_POSTFIELDSIZE 和 CURLOPT_POSTFIELDSIZE_LARGE 选项,还提供了一些其他的控制文件上传的选项,如 CURLOPT_READFUNCTION 和 CURLOPT_READDATA 等,根据实际业务需求选择合适的选项。