最近我在使用libcurl库开发ftp客户端的时候,遇到了一个问题,部分ftp服务器不支持中文路径,后来研究了一下,发现是因为ftp服务器的编码问题,例如filezilla Server采用UTF-8编码,这很好,几乎不会遇到编码格式的问题。ServU,尤其是老版本大多采用gbk编码,我在编写代码时就遇到中文路径无法处理的情况,下面是我的解决思路。
我本地代码默认是UTF-8编码格式,转换远程ftp路径的编码格式,强制转换为gbk编码,同理,如果代码中默认是gbk编码,遇到无法上传的问题,那就强制转换为UTF-8编码格式:
// 将 QString 转换为 GBK 编码的 QByteArray
QTextCodec *codec = QTextCodec::codecForName("GBK");
QByteArray fullFtpUrlEncoded = codec->fromUnicode(fullFtpUrl);
// 将 QByteArray 转换为 char*
const char* fullFtpUrlCStr = fullFtpUrlEncoded.constData();
完整FTP上传代码:
// FTP上传回调函数
static size_t read_callback(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
return fread(ptr, size, nmemb, stream);
}
bool uploadFile(const QString& localPath,const QString& remotePath)
{
bool flag=false;
CURL *curl;
CURLcode res;
QFileInfo fileInfo(localPath);
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (curl)
{
std::wstring wFilePath = localPath.toStdWString(); // 转换为宽字符串
FILE *file = _wfopen(wFilePath.c_str(), L"rb"); // 使用 _wfopen 打开文件
if (file)
{
// 设置FTP URL,这里需要替换为实际的URL
QString remotePath_Modified=remotePath;
QString fullFtpUrl = QString("%1%2").arg(HostUrl, remotePath_Modified);
// 将 QString 转换为 GBK 编码的 QByteArray
QTextCodec *codec = QTextCodec::codecForName("GBK");
QByteArray fullFtpUrlEncoded = codec->fromUnicode(fullFtpUrl);
// 将 QByteArray 转换为 char*
const char* fullFtpUrlCStr = fullFtpUrlEncoded.constData();
// 设置 CURLOPT_URL
curl_easy_setopt(curl, CURLOPT_URL, fullFtpUrlCStr);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl,CURLOPT_USERNAME,UserName.toStdString().c_str());
curl_easy_setopt(curl,CURLOPT_PASSWORD,UserPassword.toStdString().c_str());
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
curl_easy_setopt(curl, CURLOPT_READDATA, file);
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileInfo.size());
curl_easy_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS, 1L);
// 启用详细日志记录
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
// 使用被动模式
curl_easy_setopt(curl, CURLOPT_FTPPORT, "-");
// 执行FTP上传
res = curl_easy_perform(curl);
// 检查错误
if (res != CURLE_OK)
{
qDebug() << "FTP upload failed:" << curl_easy_strerror(res);
flag=false;
} else {
flag=true;
qDebug() << "FTP upload successful!";
}
fclose(file);
} else {
flag=false;
qDebug() << "Failed to open file for reading:" << fileInfo.absoluteFilePath();
}
// 清理
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return flag;
}