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);//從源路徑將文件複製到目標路徑
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章