Qt开发程序用QProcess调用curl命令上传文件并获取响应的文件
1.需求
做一个批量数字签名的工具,从一个文件夹内寻找所有的exe文件,然后复制到另外一个文件夹中,并且保存源文件的路径,将目标文件夹内的所有exe文件上传到公司的数字签名平台去做数字签名,并且返回接收后的文件;
尝试了libcurl的post请求,发现总是返回参数错误;
int HttpClient::PostFile(std::string strFile) { std::string strurl = "http://10.1.13.228/sign"; int iret = -1; struct curl_httppost *formpost = NULL; struct curl_httppost *lastptr = NULL; QFileInfo fileinfo(strFile.c_str()); std::string strFilePath = fileinfo.absolutePath().toStdString(); std::string strFileName = fileinfo.fileName().toStdString(); QFile file(strFile.c_str()); int filesize = file.size(); QByteArray pBuffer = file.readAll(); int buffsize = pBuffer.size(); if (pBuffer.size() != fileinfo.size()) { printf("read file failed\n"); return -iret; } /* */ //curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "upfile", CURLFORM_FILE, strFile.c_str(), CURLFORM_CONTENTTYPE, "text/xml", CURLFORM_END); //curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "filename", CURLFORM_COPYCONTENTS, strFileName.c_str(), CURLFORM_END); //curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "action", CURLFORM_COPYCONTENTS, "upload", CURLFORM_END); CURL* curl = curl_easy_init(); //curl_formadd(&formpost, &lastptr, // CURLFORM_COPYNAME, "uploadfile", // CURLFORM_FILE, strFilePath.c_str(),//imagepath // CURLFORM_CONTENTTYPE, "multipart/form-data", // CURLFORM_END); //curl_formadd(&formpost, &lastptr, // CURLFORM_COPYNAME, "filename", // CURLFORM_COPYCONTENTS, strFileName.c_str(), // CURLFORM_END); if (curl) { /*curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "file", CURLFORM_BUFFER, strFileName.c_str(), CURLFORM_BUFFERPTR, pReadBuffer, CURLFORM_BUFFERLENGTH, fileinfo.size(), CURLFORM_CONTENTTYPE, "application/octet-stream", CURLFORM_END);*/ /*curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "fileUpload", CURLFORM_FILE, strFile.c_str(), CURLFORM_END);*/ curl_formadd(&formpost, &lastptr, CURLFORM_PTRNAME, "reqformat", CURLFORM_PTRCONTENTS, "plain", CURLFORM_END); curl_formadd(&formpost, &lastptr, CURLFORM_PTRNAME, "file", CURLFORM_PTRCONTENTS, pBuffer, CURLFORM_CONTENTSLENGTH, pBuffer.size(), CURLFORM_END); ///* Fill in the filename field */ curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "filename", CURLFORM_COPYCONTENTS, strFileName.c_str(), CURLFORM_END); //curl_formadd(&formpost, &lastptr, CURLFORM_PTRNAME, "file", CURLFORM_FILE, strFile.c_str(), CURLFORM_END); /* Fill in the submit field too, even if this is rarely needed */ curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); //curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 5); // 重定向次数 ///curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);//设置301、302跳转跟随location curl_easy_setopt(curl, CURLOPT_URL, strurl.c_str()); //curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10);// 超时10秒 if (0 == strncmp(strurl.c_str(), "https:", 6)) { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false); } struct curl_slist *headers = NULL; std::string strfiletext = "file:@" + strFile; headers = curl_slist_append(headers, "Content-Type:multipart/form-data"); headers = curl_slist_append(headers, strfiletext.c_str()); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); char* raw_parame = ""; //char* escap_param = curl_escape(raw_parame, strlen(raw_parame)); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, raw_parame); /* 长参数一定要设置CURLOPT_POSTFIELDSIZE,否则会截断 */ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(raw_parame)); FILE *pagefile; //写入到文件 QString strOutPath = fileinfo.absolutePath().toStdString().c_str(); strOutPath+="/output/"; QDir dir(strOutPath); if (!dir.exists()) { dir.mkpath((strOutPath)); } std::string strSigniturFile = fileinfo.absolutePath().toStdString() + "/output/" + strFileName; QFile Outputfileinfo(strSigniturFile.c_str()); if (Outputfileinfo.exists()) { Outputfileinfo.remove(); } pagefile = fopen(strSigniturFile.c_str(), "wb"); if (pagefile) { curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteFile); curl_easy_setopt(curl, CURLOPT_WRITEDATA, pagefile); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } fclose(pagefile); printf("************************************\n"); } else { printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"); } if (curl) { curl_easy_cleanup(curl); } if (headers) { } } return iret; }
发现总是包参数错误;
后来发现可以curl加命令参数的方式上传程序文件去签名;前提是电脑必须安装了curl,可以打开window程序cmd.exe,然后查看curl --version 查看本地电脑的curl版本;
#include "UploadFileThread.h" #include <QProcess> UploadFileThread::UploadFileThread() { } UploadFileThread::~UploadFileThread() { } void UploadFileThread::SetFiles(QMap<QString, QString> taskInfo) { m_taskInfo = taskInfo; start(); } void UploadFileThread::run() { int s = 0; for (auto is = m_taskInfo.begin(); is != m_taskInfo.end(); is++) { QString strPath = is.key(); strPath = strPath.replace("/", "\\"); QStringList strParameter; //strParameter << "curl"; strParameter << "-F"; strParameter << "fd=sha256"; strParameter << "-F"; strParameter << ("file=@"+ strPath); strParameter << "-F"; strParameter << "cert_type=EV"; strParameter << "http://109.1.13.228"; strParameter << "-k"; strParameter << "-f"; strParameter << "-o"; strParameter << strPath; QProcess process(this); process.execute("curl", strParameter); process.waitForStarted(); process.waitForFinished(); s++; emit signalProgress(int(100.0*(s) / m_taskInfo.size())); } }
界面步骤实现函数
#include "signature.h" #include "MultiFileDirDialog.h" #include <QFileInfoList> #include "curl.h" #include<QProcess> #include <QMessageBox> #pragma execution_character_set("utf-8") signature::signature(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); setWindowTitle(tr("批量数字签名工具")); connect(ui.pBSouuce, &QPushButton::clicked, this, [=]() { QString strPath = SlotGetPath(); ui.lineEditInputPath->setText(strPath); StartSearchFile(); }); connect(ui.pBTarget, &QPushButton::clicked, this, [=]() { QString strPath = SlotGetPath(); ui.lineEditOutPutPath->setText(strPath); m_strTargetPath = strPath; }); ui.tableWidget->setColumnCount(2); connect(ui.pBSearch, &QPushButton::clicked, this, [=]() { StartSearchFile(); }); connect(ui.pushCopyFile, &QPushButton::clicked, this, [=]() { StartCopyFile(); }); ui.tableWidget->setColumnCount(2); connect(ui.pushReturn, &QPushButton::clicked, this, [=]() { CopyFileToSourcePath(); }); connect(ui.pBUpload, &QPushButton::clicked, this, [=]() { StartUploadFileToSignature(); }); m_mapExceptFile["vcredist_x86_2015.exe"] = "vcredist_x86_2015.exe"; m_mapExceptFile["vcredist_x86_2008.exe"] = "vcredist_x86_2008.exe"; m_mapExceptFile["vcredist_x64_2015.exe"] = "vcredist_x64_2015.exe"; m_mapExceptFile["vcredist_x64_2008.exe"] = "vcredist_x64_2008.exe"; m_mapExceptFile["JITComVCTK_S.exe"] = "JITComVCTK_S.exe"; m_mapExceptFile["7za.exe"] = "7za.exe"; m_mapExceptFile["openssl.exe"] = "openssl.exe"; m_mapExceptFile["iDentifyCmd.exe"] = "iDentifyCmd.exe"; m_mapExceptFile["WinPcap_4_1_3.exe"] = "WinPcap_4_1_3.exe"; //curl_global_init(CURL_GLOBAL_ALL); ui.widgetProgress->hide(); connect(&m_UploadFileThread, &UploadFileThread::signalProgress, this, [=](int progrss) { ui.progressBar->setValue(progrss); }, Qt::QueuedConnection); connect(&m_UploadFileThread, &UploadFileThread::finished, this, [=]() { QMessageBox::information(NULL, "提示", QString("已完成%1程序文件的数字签名!").arg(m_mapInfo.size()), QMessageBox::Ok); ui.widgetProgress->hide(); ui.pBUpload->setDisabled(false); ui.pushCopyFile->setDisabled(false); ui.pushReturn->setDisabled(false); ui.pBSouuce->setDisabled(false); ui.pBSearch->setDisabled(false); ui.pBTarget->setDisabled(false); }, Qt::QueuedConnection); } signature::~signature() { //curl_global_cleanup(); } QString signature::SlotGetPath() { MultiFileDirDialog fileDialog(NULL); fileDialog.setOption(QFileDialog::ShowDirsOnly, true); fileDialog.setWindowTitle("选择案件文件夹,自动创建案件并导入视频"); //m_pMultiFileDialog->setFileMode(QFileDialog::Directory); if (fileDialog.exec() == QDialog::Accepted) { QStringList selectFiles = fileDialog.selectedFiles(); if (selectFiles.size() > 0) { return selectFiles[0]; } } return ""; } /*查询源文件夹exe文件*/ void signature::StartSearchFile() { QString strInputPath = ui.lineEditInputPath->text(); if (strInputPath=="") { return; } QStringList listFile; RecursiveInputDirFiles(strInputPath, listFile); if (listFile.size()==0) { return; } while (ui.tableWidget->rowCount() > 0) { ui.tableWidget->removeRow(0); } QTableWidgetItem* pItem = NULL; for (int i = 0; i < listFile.size(); i++) { QTableWidgetItem *check = new QTableWidgetItem(); check->setCheckState(Qt::Checked); //是否设置选中框 ui.tableWidget->insertRow(i); ui.tableWidget->setItem(i, 0, check); //插入复选框 pItem = new QTableWidgetItem(); pItem->setText(listFile[i]); ui.tableWidget->setItem(i, 1, pItem); } } /*复制源文件夹exe到目标文件夹下*/ void signature::StartCopyFile() { if (m_strTargetPath=="") { QMessageBox::warning(NULL, "提示", "目标文件夹为空,请选择目标文件夹", QMessageBox::Ok); return; } RemoveAllFile(m_strTargetPath); ui.textEdit->setText(""); m_mapInfo.clear(); int count = ui.tableWidget->rowCount(); QTableWidgetItem* pItem = NULL; QString strExeName = ""; for (int i=0;i<count;i++) { pItem = ui.tableWidget->item(i, 0); if (pItem==NULL) { continue; } if (pItem->checkState()!= Qt::Checked) { continue; } pItem = ui.tableWidget->item(i, 1); QString strTargetPath=""; if (pItem!=NULL) { QString strPath=pItem->text(); QFileInfo file(strPath); m_mapInfo.insert(strPath, file.fileName()); strTargetPath = m_strTargetPath + "/" + file.fileName(); QFile::copy(strPath, strTargetPath);//从源路径将文件复制到目标路径 strExeName += file.fileName(); strExeName += "\n"; } } ui.textEdit->setText(strExeName); } /*开始上传文件进行签名*/ void signature::StartUploadFileToSignature() { if (m_mapInfo.size()==0) { QMessageBox::warning(NULL, "提示","未选中的需要上传的exe文件!",QMessageBox::Ok); return; } ui.progressBar->setValue(0); ui.widgetProgress->show(); m_UploadFileThread.SetFiles(m_mapInfo); ui.pBUpload->setDisabled(true); ui.pushCopyFile->setDisabled(true); ui.pushReturn->setDisabled(true); ui.pBSouuce->setDisabled(true); ui.pBSearch->setDisabled(true); ui.pBTarget->setDisabled(true); } /*递归遍历文件夹下面的子文件夹,查找exe程序*/ void signature::RecursiveInputDirFiles(QString strDir, QStringList& ExeFiles) { QDir dirFile(strDir); QDir dirDir(strDir); if (!dirDir.exists()) { return; } dirFile.setSorting(QDir::Time);//优先显示目录 dirDir.setSorting(QDir::Time); //列出dir(path)目录文件下所有文件和目录信息,存储到file_list容器 QStringList fileNameFilter; //视频格式 fileNameFilter << "*.exe"; dirFile.setNameFilters(fileNameFilter); QFileInfoList file_list = dirFile.entryInfoList(QDir::Files );//| QDir::Hidden | QDir::NoSymLinks //列出dir(path)目录下所有子文件夹 QFileInfoList folder_list = dirDir.entryInfoList(QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot); if (file_list.size() == 0 && folder_list.size() == 0) { return; } //添加视频文件到列表 QString strfilepath = ""; for (int i = 0; i < file_list.size(); i++) { strfilepath = file_list[i].absoluteFilePath(); QFileInfo file(strfilepath); QString strFileName = file.fileName(); if (m_mapExceptFile.find(strFileName) != m_mapExceptFile.end()) { continue; } ExeFiles.append(strfilepath); } //进行子文件夹folder_list递归遍历,将内容存入file_list容器 for (int i = 0; i != folder_list.size(); i++) { RecursiveInputDirFiles(folder_list.at(i).absoluteFilePath(), ExeFiles); } } /*先清空目标文件夹下的exe文件*/ void signature::RemoveAllFile(QString strPath) { QDir dirFile(strPath); QFileInfoList file_list = dirFile.entryInfoList(QDir::Files);//| QDir::Hidden | QDir::NoSymLinks //列出dir(path)目录下所有子文件夹 //添加视频文件到列表 QString strfilepath = ""; for (int i = 0; i < file_list.size(); i++) { strfilepath = file_list[i].absoluteFilePath(); QFile::remove(strfilepath); } } /*用目标文件夹下的签名文件反向替换源文件夹下的未签名文件*/ void signature::CopyFileToSourcePath() { for (auto it=m_mapInfo.begin();it!=m_mapInfo.end();it++) { QString strTartget = m_strTargetPath + "/"+it.value(); QString strSource = it.key(); QFile::remove(strSource); QFile::copy(strTartget, strSource);//从源路径将文件复制到目标路径 } }
自己开发了一个股票智能分析软件,功能很强大,需要的关注微信公众号:QStockView
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
2022-01-24 股票星期几买涨的概率大?
2022-01-24 四个参数秒懂巴菲特价值投资
2020-01-24 7.3 Shuffle过程和排序
2020-01-24 注册表的操作1314错误原因权限问题
2020-01-24 linux makefile编写 dump分析 GDB调试 抓包
2020-01-24 7.3.3mapreduce配置调优