QNetworkAccessManager を使用して http マルチパートを専用サーバーにアップロードしようとしています。
マルチパートは、アップロードされるデータを記述する JSON パートで構成されます。
データは、データを暗号化するシリアル QIODevice から読み取られます。
これは、マルチパート リクエストを作成するコードです。
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart metaPart;
metaPart.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
metaPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"metadata\""));
metaPart.setBody(meta.toJson());
multiPart->append(metaPart);
QHttpPart filePart;
filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(fileFormat));
filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\""));
filePart.setBodyDevice(p_encDevice);
p_encDevice->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart
multiPart->append(filePart);
QNetworkAccessManager netMgr;
QScopedPointer<QNetworkReply> reply( netMgr.post(request, multiPart) );
multiPart->setParent(reply.data()); // delete the multiPart with the reply
p_encDevice が QFile のインスタンスである場合、そのファイルは問題なくアップロードされます。
特殊な暗号化 QIODevice (シリアル デバイス) が使用されている場合、すべてのデータがカスタム デバイスから読み取られます。ただし、QNetworkAccessManager::post() は完了しません (ハングします)。
QHttpPartのドキュメントを読みました:
デバイスがシーケンシャルな場合 (たとえば、ファイルではなくソケット)、QNetworkAccessManager::post() は、デバイスが finished() を発行した後に呼び出す必要があります。
残念ながら、私はそれを行う方法がわかりません。
お知らせ下さい。
編集:
QIODevice には finished() スロットがまったくありません。さらに、QNetworkAccessManager::post() が呼び出されない場合、カスタム IODevice からの読み取りはまったく行われないため、デバイスはそのようなイベントを発行できません。(キャッチ22?)
編集2:
QNAM はシーケンシャル デバイスではまったく機能しないようです。qt-project の議論を参照してください。
編集3:
私はなんとか QNAM を「騙して」、ノンシーケンシャル デバイスから読み取っていると思わせましたが、シークおよびリセット機能によってシークが妨げられました。これは、QNAM が実際にシークを試みるまで機能します。
bool AesDevice::isSequential() const
{
return false;
}
bool AesDevice::reset()
{
if (this->pos() != 0) {
return false;
}
return QIODevice::reset();
}
bool AesDevice::seek(qint64 pos)
{
if (this->pos() != pos) {
return false;
}
return QIODevice::seek(pos);
}