3

我正在编写一个图像上传小部件,它将数据发送到 PHP 脚本并从 PHP 脚本获取新上传的文件名作为 http 响应。

@jdi,这是一个问题,现在我得到“?”作为 qDebug() << rep->readAll() 的响应,所以第一个 readAll 会清除缓冲区。

QByteArray bytes;
QBuffer buffer(&bytes);
buffer.open(QIODevice::WriteOnly);
image->save(&buffer, "JPG");

QNetworkAccessManager *http=new QNetworkAccessManager(this);
QNetworkRequest r(QUrl("http://domain/test.php"));

QString bound="---------------------------723690991551375881941828858";
QByteArray data(QString("--"+bound+"\r\n").toAscii());
data += "Content-Disposition: form-data; name=\"action\"\r\n\r\n";
data += "\r\n";
data += QString("--" + bound + "\r\n").toAscii();
data += "Content-Disposition: form-data; name=\"file\"; filename=\"test.jpg\"\r\n";
data += "Content-Type: image/JPG\r\n\r\n";
data += bytes;
data += "\r\n";
data += QString("--" + bound + "\r\n").toAscii();
data += QString("--" + bound + "\r\n").toAscii();
data += "Content-Disposition: form-data; name=\"desc\"\r\n\r\n";
data += "Description for my image here :)\r\n";
data += "\r\n";
r.setRawHeader(QString("Accept-Encoding").toAscii(), QString("gzip,deflate").toAscii());
r.setRawHeader(QString("Content-Type").toAscii(),QString("multipart/form-data; boundary=" + bound).toAscii());
r.setRawHeader(QString("Content-Length").toAscii(), QString::number(data.length()).toAscii());

rep = http->post(r,data);
connect(http,SIGNAL(finished(QNetworkReply*)),this,SLOT(uploadFinished(QNetworkReply*)));

以及回调函数:

void UploadWidget::uploadFinished(QNetworkReply* r)
{
    r->deleteLater();
    if(r->error() == QNetworkReply::NoError) {
        QByteArray data = r->readAll();
        //QString s = r->readAll(); solved - readAll clears the buffer :)
    }
}

我用 QByteArray b = rep->readAll() 迭代;for (int i = 0 ; i< b.size(); i++) { qDebug() << (char)b.at(i); 有什么方法可以将整个字节数组转换为 Qstring,因为我只得到一些符号

? 3、ÉE、VcD?? Ô â C ö f § 应该是“1这是一个测试1”

4

1 回答 1

2

显然,从您的评论来看,您的问题是您不止一次地阅读了所有响应对象。响应对象是一个顺序 IO 对象,因此一旦您读取它,它就消失了。

QNetworkReply 是一个顺序访问的 QIODevice,这意味着一旦从对象中读取数据,它就不再由设备保存。

阅读一次以获取 QByteArray。您可以将其转换为 QString。

QByteArray data = r->readAll();
QString dataStr(data);
qDebug() << dataStr;

另一件需要注意的是,您不应该在每次上传调用中创建一个全新的 QNetworkAccessManager。您每次都在泄漏它,并且几乎错过了这样一个事实,即为整个应用程序保留一个会自动为您排队多个请求。为您的整个应用程序创建一个并共享它。

此外,您可能想考虑使用方法的QHttpMultipart版本post,因为它似乎是一种更简洁的方式来设置所有标题。您几乎可以复制给定的方法,该方法用于发布 jpeg:

QHttpMultipart JPEG 帖子示例


更新

读取数据问题的实际原因是此标头:

r.setRawHeader(QString("Accept-Encoding").toAscii(), 
               QString("gzip,deflate").toAscii());

它告诉服务器以 gzip 压缩的形式发回结果。您最终阅读的内容必须首先解压缩。只需删除该标题,您应该会收到纯文本测试响应。

测试

接收器.h

#include <QObject>

class QNetworkReply;

class Receiver : public QObject
{
    Q_OBJECT
public:
    explicit Receiver(QObject* parent = 0);
public slots:
    void finished(QNetworkReply*);
};

主文件

#include <QCoreApplication>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QDebug>

#include "receiver.h"

Receiver::Receiver(QObject *parent)
    : QObject(parent)
{}

void Receiver::finished(QNetworkReply *reply) {
    reply->deleteLater();
    QByteArray data = reply->readAll();
    qDebug() << data;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QNetworkAccessManager net;
    Receiver rec;

    net.connect(&net, SIGNAL(finished(QNetworkReply*)),
                &rec, SLOT(finished(QNetworkReply*)));

    QNetworkRequest r(QUrl("http://poki.ba/test.html"));
    r.setHeader(r.ContentTypeHeader, QVariant("multipart/form-data;"));
    r.setHeader(r.ContentLengthHeader, QVariant("100"));
//    r.setRawHeader(QString("Accept-Encoding").toAscii(),
//                   QString("gzip,deflate").toAscii());

    net.post(r, QByteArray());

    return a.exec();
}
于 2012-11-26T01:47:21.690 回答