У меня проблемы с приложением Qt; в частности, с классом QNetworkAccessManager. Я пытаюсь выполнить простую HTTP-загрузку двоичного файла, используя метод post () QNetworkAccessManager. В документации говорится, что я могу дать указатель на QIODevice для post () и что класс будет передавать данные, найденные в QIODevice. Это говорит мне о том, что я должен иметь возможность дать post () указатель на QFile. Например:
QFile compressedFile("temp");
compressedFile.open(QIODevice::ReadOnly);
netManager.post(QNetworkRequest(QUrl("http://mywebsite.com/upload") ), &compressedFile);
Похоже, что происходит в системе Windows, где я разрабатываю, это то, что мое приложение Qt выталкивает данные из QFile, но затем не завершает запрос; кажется, что он сидит там и ждет, пока из файла не появится больше данных. Почтовый запрос не «закрывается» до тех пор, пока я не убью приложение вручную, после чего на моем сервере появится весь файл.
Из некоторых отладок и исследований я думаю, что это происходит потому, что операция чтения () в QFile не возвращает -1, когда вы достигаете конца файла. Я думаю, что QNetworkAccessManager пытается читать из QIODevice, пока не получит -1 от read (), и в этот момент он предполагает, что данных больше нет, и закрывает запрос. Если он продолжает получать нулевой код возврата от read (), QNetworkAccessManager предполагает, что может быть больше поступающих данных, и поэтому он продолжает ожидать эти гипотетические данные.
Я с некоторым тестовым кодом подтвердил, что операция read () в QFile просто возвращает ноль после того, как вы прочитали до конца файла. Кажется, это несовместимо с тем, как метод post () QNetworkAccessManager ожидает, что QIODevice будет вести себя. Мои вопросы:
- Является ли это каким-то ограничением работы QFile под Windows?
- Есть ли какой-то другой способ, которым я должен использовать QFile или QNetworkAccessManager для отправки файла с помощью post ()?
- Разве это не сработает вообще, и мне нужно будет найти какой-то другой способ загрузить мой файл?
Будем благодарны за любые предложения или советы.
Обновление: Оказывается, у меня были две разные проблемы: одна на стороне клиента и одна на стороне сервера. На стороне клиента я должен был убедиться, что мой объект QFile остался в течение всей сетевой транзакции. Метод post () QNetworkAccessManager возвращается немедленно, но на самом деле не завершается немедленно. Вам необходимо прикрепить слот к сигналу finish () QNetworkAccessManager, чтобы определить, когда фактически завершился POST. В моем случае было достаточно легко хранить QFile более или менее постоянно, но я также прикрепил слот к сигналу finish (), чтобы проверить наличие сообщений об ошибках от сервера.
Я прикрепил сигнал к слоту так:
connect(&netManager, SIGNAL(finished(QNetworkReply*) ), this, SLOT(postFinished(QNetworkReply*) ) );
Когда пришло время отправлять мой файл, я написал такой почтовый индекс (обратите внимание, что сжатый файл является членом моего класса и поэтому не выходит за рамки этого кода):
compressedFile.open(QIODevice::ReadOnly);
netManager.post(QNetworkRequest(QUrl(httpDestination.getCString() ) ), &compressedFile);
Завершенный (QNetworkReply *) сигнал от QNetworkAccessManager вызывает мой метод postFinished (QNetworkReply *). Когда это происходит, для меня безопасно закрыть сжатый файл и удалить файл данных, представленный сжатым файлом. В целях отладки я также добавил несколько операторов printf (), чтобы подтвердить, что транзакция завершена:
void CL_QtLogCompressor::postFinished(QNetworkReply* reply)
{
QByteArray response = reply->readAll();
printf("response: %s\n", response.data() );
printf("reply error %d\n", reply->error() );
reply->deleteLater();
compressedFile.close();
compressedFile.remove();
}
Поскольку сжатый файл не закрывается сразу и не выходит за пределы области видимости, QNetworkAccessManager может передавать мой файл столько времени, сколько ему нравится. В конце концов транзакция завершена, и мой метод postFinished () вызывается.
Моя другая проблема (которая также способствовала поведению, которое я наблюдал, когда транзакция никогда не завершалась) заключалась в том, что код Python для моего веб-сервера неправильно отображал POST, но это выходит за рамки моего исходного вопроса Qt.