QT支持 超大文件 http post上传

公司开发的聊天软件,以前开发人员写的代码,超过100M的文件,就基本上崩溃,开发人员走了,无奈作为老板我只能自己修改。改完测试发送650M甚至更大文件没问题,稳定。

解决思路:

将http的post内容为 multipart/form-data 格式的,进行 格式准备,准备好的先 存到一个临时文件,再发送。以前存到一个 QByteArray 变量里,尽管按QT资料说能存2GB,但实际测试就是一存就崩,改为临时文件,当post时,第二个参数直接用文件IO就好了。

临时文件产生过程也要注意,以前直接读取全部要发的文件内容,超过200M也会崩,改为一次读写10M就好了。

为了避免临时文件造成磁盘空间占用,发送成功后的回调函数里要删除临时文件。

为了能支持多窗口同时发送多个文件,临时文件命名要使用随机数。

另外这个 缓存文件变量 m_file_tmp 要定义到 类成员里,我临时创建的缓存文件变量就不行,post时会崩。

bool ChatTransferFileThread::start()
{
    QString strfilename = m_strFilePath;
    QString strfile = "file";

    if(m_strFilePath.isEmpty() || m_strServerAddr.isEmpty())
    {
        return false;
    }

    m_file.setFileName(m_strFilePath);
    qDebug() << QString::fromLocal8Bit("上传文件名字")<< m_strFilePath;

    if (!m_file.open(QIODevice::ReadOnly)||!m_file.exists())
    {

        QMessageBox::about(NULL, QString::fromLocal8Bit("错误提示"), m_strFilePath+QString::fromLocal8Bit("文件是空文件或是文件夹"));//卢伟华
        /*QMessageBox message_cd(QMessageBox::NoIcon,QString::fromUtf8("警告"),QString::fromUtf8("您是否要关闭此软件?"));
            message_cd.addButton(QString::fromUtf8("是"), QMessageBox::AcceptRole);
            message_cd.addButton(QString::fromUtf8("否"), QMessageBox::RejectRole);
            if(message_cd.exec() == QMessageBox::AcceptRole)
            {
                m_file->close();
                this->close();
                event->accept();
            }
            else
            {
                 event->ignore();
            }*/

        m_file.close();
        return false;
    }

    //qDebug()<<"m_strJessionId"<<m_strJessionId;

    QNetworkCookie netWorkCookie = QNetworkCookie(QString("JSESSIONID1").toLatin1(), QString(m_strJessionId).toLatin1());

    QVariant var;
    var.setValue(netWorkCookie);

    QByteArray fdata = QByteArray();
    QByteArray fdata_tail = QByteArray();

    QString strBoundary = "--------------------------------------adf70as00sd0fsf";

    QMap<QString,QString> params;

    params.insert("UPLOAD_MODE", "0");
    params.insert("DURATION", "0");
    params.insert("DEST_UID", "1");

    qDebug() << QString::fromLocal8Bit("准备上传1");

    for(QMap<QString,QString>::Iterator t=params.begin();t!=params.end();t++)
    {
        fdata.append("--"+strBoundary+"\r\n");
        fdata.append(QString("Content-Disposition: form-data; name=\"")+t.key()+QString("\"")+QString("\r\n"));
        fdata.append("\r\n");
        fdata.append(t.value()+"\r\n");
    }

    //上传文件的头部
    fdata.append("--"+strBoundary+"\r\n");
    fdata.append(QString("Content-Disposition: form-data; name=\"")+strfile+QString("\"; filename=\"")+strfilename+QString("\"")+QString("\r\n"));
    fdata.append(QString("Content-Type: multipart/form-data")+QString("\r\n"));
    fdata.append("\r\n");

    qDebug() << QString::fromLocal8Bit("准备上传2");

    //生成缓存文件
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
    QString tmp_file_path=QDir::tempPath()+"/oa_upload"+QString::number(qrand())+".tmp";

    qDebug()<<QString::fromLocal8Bit("准备缓存文件") << tmp_file_path;
    m_file_tmp.setFileName(tmp_file_path);
    m_file_tmp.open(QIODevice::WriteOnly);
    m_file_tmp.write(fdata);

    //fdata.append(m_file.readAll());
    //m_file_tmp.write(m_file.readAll());

    while (!m_file.atEnd())
    {
        m_file_tmp.write(m_file.read(10000000));
    }

    qDebug() << QString::fromLocal8Bit("准备上传3");

    //---------------------------

    fdata_tail.append("\r\n");
    fdata_tail.append("--"+strBoundary+"\r\n");

    fdata_tail.append(QString("Content-Disposition: form-data; name=\"upload\"")+QString("\r\n"));
    fdata_tail.append("\r\n");
    fdata_tail.append("1\r\n");
    fdata_tail.append("--"+strBoundary+"--\r\n");

    m_file_tmp.write(fdata_tail);

    m_file_tmp.close();

    qDebug() << QString::fromLocal8Bit("准备上传4");

    //int fdata_length=fdata.length();

    QNetworkRequest request = QNetworkRequest(QUrl(m_strServerAddr));
    request.setHeader(QNetworkRequest::CookieHeader, var);
    request.setRawHeader(QString("Content-Type").toLatin1(),QString("multipart/form-data; boundary="+strBoundary).toLatin1());
    //request.setRawHeader(QString("Content-Length").toLatin1(),QString::number(fdata_length).toLatin1());
    //request.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");

    if(m_pNetWorkManager == NULL)
    {
        return false;
    }


    qDebug() << QString::fromLocal8Bit("开始上传post")<<m_strServerAddr;
    //m_pNetworkReply = m_pNetWorkManager->post(request, fdata);

    m_file_tmp.open(QIODevice::ReadOnly);
    m_pNetworkReply = m_pNetWorkManager->post(request,&m_file_tmp);

    connect(m_pNetworkReply, &QNetworkReply::uploadProgress, this, &ChatTransferFileThread::onUploadProgress);
    return true;

}
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 在Qt中进行HTTP POST方法上传文件的步骤如下: 1. 首先需要创建一个QNetworkAccessManager对象,用于处理HTTP请求和响应。 ```cpp QNetworkAccessManager *manager = new QNetworkAccessManager(this); ``` 2. 然后,创建一个QHttpMultiPart对象,用于构建请求的多部分内容。并向其添加需要上传文件。 ```cpp QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); QHttpPart filePart; filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("multipart/form-data")); filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\"filename.txt\"")); QFile *file = new QFile("Path/To/File/filename.txt"); file->open(QIODevice::ReadOnly); filePart.setBodyDevice(file); file->setParent(multiPart); // 所有权交给multiPart multiPart->append(filePart); ``` 3. 构建HTTP请求并发送。使用QNetworkRequest来设置URL和其他的请求头信息,然后使用QNetworkAccessManager的post方法发送请求。 ```cpp QUrl url("http://example.com/upload"); QNetworkRequest request(url); request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("multipart/form-data; boundary=") + multiPart->boundary()); QNetworkReply *reply = manager->post(request, multiPart); multiPart->setParent(reply); // reply对象处理多部分内容,所以所有权交给reply ``` 4. 最后,处理响应。可以通过连接QNetworkReply的信号来获取响应的结果。 ```cpp connect(reply, &QNetworkReply::finished, [=]() { if (reply->error() == QNetworkReply::NoError) { qDebug() << "Upload success"; } else { qDebug() << "Upload failed: " << reply->errorString(); } reply->deleteLater(); }); ``` 这样就完成了使用Qt进行HTTP POST方法上传文件的过程。当然,还可以添加进度跟踪、错误处理等逻辑来更完善地处理上传过程。 ### 回答2: 使用Qt进行HTTP POST上传文件的方法如下: 1. 首先,需要创建一个QFile对象来打开要上传文件。可以使用QFileDialog来选择文件,也可以使用固定文件路径。 ```cpp QFile file(filePath); if(!file.open(QIODevice::ReadOnly)){ qDebug() << "文件打开失败"; return; } ``` 2. 然后,创建一个QHttpMultiPart对象,用于创建一个HTTP POST请求。将文件内容添加到该multipart中。 ```cpp QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); QHttpPart filePart; filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\"" + file.fileName() + "\"")); filePart.setBodyDevice(&file); multiPart->append(filePart); ``` 3. 创建一个QNetworkRequest对象,设置请求的URL和HTTP方法为POST。 ```cpp QNetworkRequest request(url); request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("multipart/form-data; boundary=" + multiPart->boundary())); request.setRawHeader("Content-Length", QByteArray::number(multiPart->device()->size())); // 设置请求的长度 ``` 4. 最后,创建一个QNetworkAccessManager对象,并发送POST请求。 ```cpp QNetworkAccessManager *manager = new QNetworkAccessManager(); QNetworkReply *reply = manager->post(request, multiPart); multiPart->setParent(reply); // 确保在回复完成后,multipart对象也会被删除 connect(reply, &QNetworkReply::finished, this, [this, reply]() { if(reply->error() == QNetworkReply::NoError){ // 上传成功,进行处理 qDebug() << "文件上传成功"; } else { // 上传失败,进行错误处理 qDebug() << "文件上传失败:" << reply->errorString(); } }); file.close(); // 关闭文件 ``` 以上就是使用Qt进行HTTP POST上传文件的简单示例。需要注意的是,确保在文件上传完成后关闭文件和网络操作对象,以节省资源和避免内存泄漏。 ### 回答3: 在Qt中通过HTTP进行文件上传的方法如下: 首先,需要使用Qt网络模块中的QNetworkAccessManager类来完成HTTP请求。此类提供了发送和接收数据的功能。 其次,创建一个QNetworkRequest对象,用于设置HTTP请求的URL和其他相关信息。 然后,使用QNetworkAccessManager的post()函数发送HTTP请求。在此函数中,将QNetworkRequest对象作为参数传递,并提供待上传文件路径作为第二个参数。 最后,需要通过QNetworkReply类来处理HTTP响应。可以使用finished()信号来检测请求是否完成,并在其槽函数中获取响应的内容或处理错误。 以下是一个简单的示例代码,用于演示如何使用Qt进行HTTP文件上传: ```cpp #include <QtNetwork> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QNetworkAccessManager manager; // 创建一个QNetworkRequest对象,设置请求的URL和其他信息 QNetworkRequest request(QUrl("http://example.com/upload")); request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data"); // 待上传文件路径 QString filePath = "path/to/file.txt"; QFile file(filePath); // 打开文件,准备上传 if (file.open(QIODevice::ReadOnly)) { // 发送HTTP请求,上传文件 QNetworkReply *reply = manager.post(request, &file); // 处理HTTP响应 QObject::connect(reply, &QNetworkReply::finished, [&]() { // 检查HTTP请求是否成功 if(reply->error() == QNetworkReply::NoError) { QString response = QString(reply->readAll()); // 处理响应数据 qDebug() << "Response:" << response; } else { // 处理错误信息 qDebug() << "Error:" << reply->errorString(); } // 关闭文件和释放资源 file.close(); reply->deleteLater(); a.quit(); }); } return a.exec(); } ``` 在上面的示例代码中,我们首先创建了一个QNetworkAccessManager对象,然后构造了一个QNetworkRequest对象并设置请求的URL和Content-Type为"multipart/form-data"。接着打开要上传文件,并使用QNetworkAccessManager的post()函数发送HTTP请求,将QNetworkRequest对象和QFile对象作为参数。最后,通过QNetworkReply处理HTTP响应。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值