Я использую nreco.pdfgenerator для преобразования html в формат pdf. В настоящее время я сталкиваюсь с проблемой, когда инструмент генератора PDF выдает исключение при создании PDF-файла при размещении в других средах. Ошибка следующая:
NReco.PdfGenerator.WkHtmlToPdfException: выход с кодом 1 из-за сетевой ошибки: RemoteHostClosedError (код выхода: 1)
Я дал все необходимые разрешения для папок и файлов. Не уверен насчет этой сетевой ошибки. Может ли кто-нибудь заглянуть в него?
Спасибо
1 ответ
NReco PdfGenerator — это оболочка .NET для инструмента wkhtmltopdf, и это исключение означает, что процесс wkhtmltopdf завершился с кодом ошибки, а последнее сообщение об ошибке (из журнала консоли) было «Выход с кодом 1 из-за сетевой ошибки: RemoteHostClosedError».
Эта ошибка означает, что HTML-документ содержит ссылки на внешние ресурсы (изображения, css, js и т. д.), и по какой-то причине wkhtmltopdf не может получить к ним доступ. Убедитесь, что URL-адреса указаны правильно (если вы предоставляете HTML в виде строки C#, все URL-адреса должны быть абсолютными), а сервер, на котором выполняется wkhtmltopdf, может загрузить эти URL-адреса.
3
Vitaliy Fedorchenko
17 Янв 2017 в 18:01
I was learning the Github API and wanted to create an Issue on github by Qt.
But, when I submit my Issue, the «Debug Console» said
QNetworkReply::RemoteHostClosedError
(I catched error).
I don’t know why, please help me!
Code on Github:
void MainWindow::on_pushButton_2_clicked()
{
QString id = ui->ID_Send->text();
QJsonObject JJ;
QJsonDocument jd;
JJ["title"] = ui->Title->text();
JJ["body"] = ui->Comment->toPlainText();
QHttpMultiPart *part = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart info;
info.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/json"));
jd.setObject(JJ);
info.setBody(jd.toJson());
part->append(info);
QNetworkRequest request;
qDebug()<<"https://api.github.com/repos/MoyuSteve/Comment/issues?client_id="+
client_id+"&client_secret="+client_secret;
request.setUrl(QUrl("https://api.github.com/repos/MoyuSteve/Comment/issues?client_id="+
client_id+"&client_secret="+client_secret));
QNetworkReply* reply = manager->post(request,part);
QObject::connect(reply, &QNetworkReply::finished, [reply, this] () {
if (reply->error() == QNetworkReply::NoError) {
ui->status->setText("ok");
} else {
ui->status->setText("failed");
qDebug()<<reply->error();
}
reply->deleteLater();
});
}
1. Играю на нескольких серверах (HiTech 1.12.2, TechnoMagic, TechnoMagicRPG)
2. При попытке запустить лаунчер McSkill возникает ошибка «Ошибка при получении списка обновления: SslHandlshakeFailedError Проверьте соединение с интернетом, а так же попробуйте отключить антивирус!» Соединение норм — всё работает, лига легенд на норм пинге пашет, антивируса у меня вовсе нет.
Я попробовала:
1) добавила приложение в список разрешений брандмауэра
2) скачала и попробовала запустить McSkill.jar — вообще не запускается, даже в диспетчере задач не появляется
3) попробовала этот McSkill.jar открыть с помощью java.exe — всё равно даже в диспетчере нет
4) установила java jre1.8.0_301 — это помогло запуститься клиенту майнкрафта другого проекта, ранее показывал ошибку:
У меня на компе в ProgramFiles лежал jdk-17 и видимо оба клиента пытались запуститься через этот jdk, а не через позже установленный jre. Поустанавливала jre — клиент другого проекта то работал, то нет. При установленном jre удалила jdk оттуда нафиг — тот клиент заработал (наш — нет).
5) перезапустила комп несколько раз после разных вариантов решений проблемы (не ну мало ли, оч часто помогает))))
У меня подозрение, что это всё таки связано с версией java, которая стоит на компе, но решить чот не получается, help pls.
3. Скриншоты уже есть выше
4. Краш-лог получить не могу, до значка шестеренки даже не доходит (если это в хранилось в C:Users…AppDataRoaming то к сожалению папку McSkill я оттуда удалила).
5. discord Terapanthera#2749
- 1. QNetworkReply::ConnectionRefusedError и QNetworkReply::RemoteHostClosedError
- 2. QNetworkReply::HostNotFoundError
- 3. QNetworkReply::TimeoutError
- 4. QNetworkReply::OperationCanceledError
- 5. QNetworkReply::SslHandshakeFailedError
- 6. QNetworkReply::TemporaryNetworkFailureError и QNetworkReply::NetworkSessionFailedError
- 7. QNetworkReply::BackgroundRequestNotAllowedError
- 8. QNetworkReply::TooManyRedirectsError и QNetworkReply::InsecureRedirectError
- 9. Ошибки QNetworkReply::Proxy*
- 10. QNetworkReply::ContentAccessDenied
- 11. QNetworkReply::AuthenticationRequiredError
- 12. QNetworkReply::ContentReSendError
- 13. QNetworkReply::ContentConflictError
- 14. QNetworkReply::ContentGoneError
- 15. QNetworkReply::InternalServerError
- 16. QNetworkReply::OperationNotImplementedError
- 17. QNetworkReply::ProtocolUnknownError
- 18. QNetworkReply::ServiceUnavailableError
- 19. QNetworkReply::ProtocolInvalidOperationError
- 20. QNetworkReply::UnknownNetworkError
- 21. QNetworkReply::UnknownProxyError
- 22. Ошибки QNetworkReply::UnknownContentError,QNetworkReply::ProtocolFailure, QNetworkReply::UnknownServerError
- 23. Пример с выводом ошибки в qDebug
В одном из уроков была представлена работа с
QNetworkAccessManager
для получения содержимого страницы с сайта по протоколу
http.
Там была сделана проверка на наличие ошибок, но не были даны пояснения, какие могут быть ошибки. Для этого класс
QNetworkReply
предоставляет
enum NetworkError
, в котором перечислены коды возможных ошибок.
В случае успешного выполнения возвращается
NoError
, равный
0
.
В противном случае возвращается код ошибки из кодов, представленных ниже:
| Константа | Значение | Описание |
|---|---|---|
QNetworkReply::ConnectionRefusedError |
1 |
Удалённый сервер отклонил соединение (сервер не принимает запросы) |
QNetworkReply::RemoteHostClosedError |
2 |
удаленный сервер закрыл соединение преждевременно, до того, как весь ответ был получен и обработан |
QNetworkReply::HostNotFoundError |
3 |
удаленный хост не был найден (недействительное имя хоста) |
QNetworkReply::TimeoutError |
4 |
подключение к удаленному серверу истекло |
QNetworkReply::OperationCanceledError |
5 |
операция была отменена через вызов abort() или close() до того, как была завершена. |
QNetworkReply::SslHandshakeFailedError |
6 |
Подключение по SSL/TLS не удалось, шифрованный канал не может быть. Должен испускаться сигнал sslErrors(). |
QNetworkReply::TemporaryNetworkFailureError |
7 |
соединение было нарушено из-за отключения от сети, однако система инициировала роуминг к другой точке доступа. Запрос должен быть повторно и будет обработан, как только соединение будет восстановлено. |
QNetworkReply::NetworkSessionFailedError |
8 |
соединение было нарушено из-за отключения от сети или невозможности запуска сети. |
QNetworkReply::BackgroundRequestNotAllowedError |
9 |
запрос в настоящее время не допускается из-за политики платформы. |
QNetworkReply::TooManyRedirectsError |
10 |
количество редиректов превысило допустимый лимит. Лимит по умолчанию установлен на 50 редиректов через QNetworkRequest::setMaxRedirectsAllowed(). |
QNetworkReply::InsecureRedirectError |
11 |
во время обработки редиректов, API доступа по сети обнаружило редирект с шифрованного протокола (https) на не шифрованный (http) |
QNetworkReply::ProxyConnectionRefusedError |
101 |
в подключении к прокси-серверу было отказано (прокси-сервер не принимает запросы) |
QNetworkReply::ProxyConnectionClosedError |
102 |
прокси-сервер закрыл соединение преждевременно, до того, как весь ответ был получен и обработан |
QNetworkReply::ProxyNotFoundError |
103 |
прокси-хост не был найден (недействительное имя прокси хоста) |
QNetworkReply::ProxyTimeoutError |
104 |
подключение к прокси-серверу истекло или прокси-сервер не ответил вовремя на отправленный запрос |
QNetworkReply::ProxyAuthenticationRequiredError |
105 |
прокси-сервер требует аутентификации для того, чтобы удовлетворить запрос, но не принял каких-либо предложенных учётных данных (если таковые имеются) |
QNetworkReply::ContentAccessDenied |
201 |
в доступе к удаленному контенту было отказано (по аналогии с ошибкой HTTP 401) |
QNetworkReply::ContentOperationNotPermittedError |
202 |
Запрошенная операция на удаленное содержимое не допускается |
QNetworkReply::ContentNotFoundError |
203 |
удаленный контент не был найден на сервере (аналогично ошибке HTTP 404) |
QNetworkReply::AuthenticationRequiredError |
204 |
удаленный сервер требует аутентификации, чтобы предоставить контент, но предоставленные учетные данные не были приняты (если таковые имеются) |
QNetworkReply::ContentReSendError |
205 |
запрос необходимо отправить повторно, но это не удалось, например, потому что загрузка данных не может быть прочитана во второй раз. |
QNetworkReply::ContentConflictError |
206 |
запрос не может быть завершен из-за конфликта с текущим состоянием ресурса. |
QNetworkReply::ContentGoneError |
207 |
запрошенный ресурс больше не доступен на сервере. |
QNetworkReply::InternalServerError |
401 |
Сервер столкнулся с непредвиденным условием, которое не позволяет ему выполнить запрос. |
QNetworkReply::OperationNotImplementedError |
402 |
сервер не поддерживает функциональные возможности, необходимые для выполнения запроса. |
QNetworkReply::ServiceUnavailableError |
403 |
сервер не может обработать запрос в данный момент. |
QNetworkReply::ProtocolUnknownError |
301 |
Network Access API не может удовлетворить запрос, потому что протокол не известен |
QNetworkReply::ProtocolInvalidOperationError |
302 |
запрошенная операция недопустима для этого протокола |
QNetworkReply::UnknownNetworkError |
99 |
была обнаружена неизвестная ошибка сети |
QNetworkReply::UnknownProxyError |
199 |
была обнаружена неизвестная ошибка прокси |
QNetworkReply::UnknownContentError |
299 |
была обнаружена неизвестная ошибка, связанная с удаленным содержимым |
QNetworkReply::ProtocolFailure |
399 |
был обнаружен сбой в протоколе (ошибка синтаксического анализа, недействительные или неожиданные ответы и т.д.) |
QNetworkReply::UnknownServerError |
499 |
была обнаружена неизвестная ошибка, связанная с ответом сервера |
После изучения данного списка ошибок можно сделать вывод, что данный список объединяет в себе значительно больший список ошибок, чем, например, тот список кодов ошибок, который может вернуть http сервер. Давайте поговорим немного о возможных ошибках и из-за чего они могут возникнуть.
QNetworkReply::ConnectionRefusedError и QNetworkReply::RemoteHostClosedError
Если говорить об интерпретации данных ошибок, то наиболее ярким примером для меня является подключение по SSH к другому хосту. Смысл ошибок в том, что в первом случае сервер нас не пускает, а во втором случае соединение могло быть закрыто по истечению определённого периода времени.
Также ошибка ConnectionRefusedError может возникать в случаях, когда на определённом порту ПК просто нет службы, которая могла бы обработать запрос.
QNetworkReply::HostNotFoundError
Пожалуй довольно понятная ошибка, которая обозначает, что вы просто ввели неверный ip адрес или домен, с которого пытаетесь получить данные. Также, такая ошибка может возникнуть в том случае, если домен перестал быть доступен в сети. Данная ошибка аналогична ошибке номер
105 —
ERR_NAME_NOT_RESOLVED (HTTP).
QNetworkReply::TimeoutError
Превышен интервал ожидания. Наиболее близкое сравнение — это использование протокола ICMP, проверка доступности узла в сети, когда производим его ping. То есть узел в сети вроде бы и есть, но он не отвечает.
QNetworkReply::OperationCanceledError
А вот ошибка, которая будет относится уже к действиям самой программы на Qt. В данном случае она будет возникать тогда, когда логика программы прерывает получение данных через
QNetworkAccessManager.
То есть данная ошибка не должна возникать в том случае, если операция получения данных была прервана извне. Поэтому, если Вы отлавливаете подобную ошибку, то ищите проблему внутри вашей собственной программы.
QNetworkReply::SslHandshakeFailedError
Для установления шифрованных каналов связи, которые используют SSL шифрование, требуется установка соединения через операции квитирования, то есть через подтверждение приёма/передачи информации. В данном случае осуществляется согласование параметров шифрования, передача сеансового ключа, а также необязательные операции аутентификации сервера клиентом и клиента сервером. Если что-то из перечисленного пойдёт не так, то будет выброшена данная ошибка.
QNetworkReply::TemporaryNetworkFailureError и QNetworkReply::NetworkSessionFailedError
Возникновение данных ошибок может быть вызвано любой неполадкой в сети вплоть до падения физического подключения к сети. Проверять подключения можно через класс
QNetworkInterface.
Класс
QNetworkInterface
имеет статический метод
QList
QNetworkInterface::allInterfaces()
, который возвращает список всех интерфейсов на вашем ПК. При этом будут учитываться абсолютно все соединения, вплоть до соединений, которые были созданы для виртуальной машины, например, для
Virtual Box.
Тут к слову возникает очень интересный момент, когда ведётся разработка программного обеспечения, которое должно работать по сети, и при этом у разработчика имеется виртуальная машина на борту, особенно если она запущена, то необходимо учитывать этот момент, поскольку программа может пытаться получить данные через соединение с виртуальной машиной, то есть будет считать что сеть доступна, хотя разработчик будет тестировать User Case при отключённом соединении. Впрочем, даже выключенная виртуальная машина будет вызывать некоторые проблемы, поскольку соединение будет активно, хотя Link и не будет поднят.
Поэтому, чтобы понять, что не так, при получении ошибок
QNetworkReply::TemporaryNetworkFailureErro
r и
QNetworkReply::NetworkSessionFailedError
придётся протестировать интерфейсы ПК на предмет активности:
QNetworkInterface::IsUp
и
QNetworkInterface::IsRunning.
QNetworkReply::BackgroundRequestNotAllowedError
А вот эта ошибка зависит непосредственно от политик платформы, для которой разрабатывается приложение. Например, если под некоторым абстрактным Android устройством запрещён обмен информацией по сети в энергосберегающем режиме, то в данном режиме мы будем получать именно эту ошибку, при попытке обмена информацией.
QNetworkReply::TooManyRedirectsError и QNetworkReply::InsecureRedirectError
А вот эти ошибки из разряда новенького в Qt 5.6. Теперь можно отслеживать превышения количества редиректов со страниц сайтов, а также редиректы со страниц с шифрованием https на страницы без шифрования. Что может быть полезно для разработки программного обеспечения для анализа сайтов.
Без дополнительных настроек данные ошибки как правило не возникают. Дело в том, что когда задаётся
QNetworkRequest
и в него не устанавливаются флаги конфигурации, то при попытке запроса страницы с сайта, с которой осуществляется редирект, не будет происходить перехода на новый url, а в
QNetworkReply
не будет никакого полезного контента. Поэтому потребуется установить в
QNetworkRequest
флаг
QNetworkRequest::FollowRedirectsAttribute,
тогда QNetworkAccessManager будет переходить по редиректам, пока не получит итоговую страницу или не превысит ограничение на количество переходов. По умолчанию количество переходов ограничено 50-ю.
Установка атрибута может производиться следующим образом:
QNetworkRequest request; request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, QVariant(true));Что касается
QNetworkReply::InsecureRedirectError,
то смысл заключается в том, чтобы отследить редирект на небезопасный протокол.Ошибки QNetworkReply::Proxy*
Следующие пять ошибок аналогичны по своему характеру ошибкам подключения к серверам без проксирования.
QNetworkReply::ContentAccessDenied
В документации сказано, что данная ошибка аналогична ошибке 401 в HTTP, то есть требуется авторизация, но полагаю, что данная ошибка может возникать и в случаях получения кода 403 и 407. Ошибка 407 аналогична ошибке 401, но используется для прокси-сервера. А ошибка 403 является порождающей для ошибок 401 и 407.
QNetworkReply::AuthenticationRequiredError
Данная ошибка характерна для HTTP протокола. Дело в том, что http протокол поддерживает схемы проверки подлинности. В данном случае необходимо посылать запрос на сервер с установкой логина и пароля. Замечу, что это напрямую означает то, что Вы можете написать приложение на Qt, которое будет аутентифицироваться на сайтах и выполнять определённые действия на сайте уже в авторизованном режиме, то есть можно написать и бота для работы на сайте.
Решение проблемы заключается в том, чтобы установить логин и пароль пользователя в QAuthenticator, который будет подмешивать учётные данные к запросу. Причем делаться это будет в автоматическом режиме по сигналу
QNetworkAccessManager::authenticationRequired,
при этом логин и пароль будут кешированы, так что сигнал не будет испускаться при каждом запросе.connect(&m_manager,&QNetworkAccessManager::authenticationRequired, [this](QNetworkReply *rep, QAuthenticator* auth){ auth->setUser("username"); auth->setPassword("passwordd"); });QNetworkReply::ContentReSendError
Провести какую-либо точную аналогию с кодами HTTP для этой ошибки является затруднительным, поскольку вызываться она может различными причинами.
QNetworkReply::ContentConflictError
Данная ошибка соответствует ошибке
409 Confilct
в протоколе HTTP.QNetworkReply::ContentGoneError
Данная ошибка соответствует ошибке
410 Gone (Удалён)
в протоколе HTTP.QNetworkReply::InternalServerError
Данная ошибка соответствует ошибке
500 Internal Server Error (Внутренняя ошибка сервера)
в протоколе http.QNetworkReply::OperationNotImplementedError
Данная ошибка соответствует ошибке
501 Not Implemented (Не реализовано)
в протоколе http. Возникает такая тогда, когда Вы пытаетесь выполнить, например, запрос POST к URL, по которому сервер обрабатывает только GET запросы.Такое поведение можно встретить, например, в
Django
проекте. Если запрос не реализован, то сервер с Django отправит пустую страницу на POST запрос с данным кодом.
QNetworkReply::ProtocolUnknownError
Такая ошибка, как
QNetworkReply::ProtocolUnknownError,
может возникнуть из-за того, что в запрос был передан url без указания типа протокола, то есть вместо
http://www.example.com
было передано
//www.example.com
Такая проблема может возникнуть в том случае, если вы парсите страницы и извлекаете url изображений. Например, на данном сайте адреса всех изображений в статьях выглядят следующим образом
/media/uploads/2017/02/03/testquickwidget.jpg
То есть не указывается протокол и домен сайта. Поэтому если Вы извлечёте все адреса изображений со страницы, то не сможете скачать изображения без дополнительной обработки, а именно без подстановки домена и протокола в начале строки, получив данную ошибку.
QNetworkReply::ServiceUnavailableError
Соответствует ошибке
503 Service Unavailable («сервис недоступен»)
в протоколе httpQNetworkReply::ProtocolInvalidOperationError
В данном случае протокол определён, но точное соответствие ошибке из протокола http не прослеживается, относительно других протоколов также может быть что угодно.
QNetworkReply::UnknownNetworkError
Наиболее частый вариант того, чему может соответствовать данная ошибка является ошибка шлюза
502 Bad Gateway («плохой, ошибочный шлюз»)
в протоколу httpQNetworkReply::UnknownProxyError
Также может быть ошибка 502, но уже в варианте с прокси-сервером
Ошибки QNetworkReply::UnknownContentError,QNetworkReply::ProtocolFailure, QNetworkReply::UnknownServerError
С данными ошибками затрудняюсь найти рабочее соответствие, буду рад подсказке, если кто сталкивался.
Пример с выводом ошибки в qDebug
Можно проверять ошибку по сигналу завершения запроса от
QNetworkAccessManager
в слоте, который подключается для обработки результата запроса.manager = new QNetworkAccessManager(this); connect(manager, &QNetworkAccessManager::finished, this, &Downloader::onResult);В данном случае имеется класс-обёртка над классом
QNetworkAccessManager
с названием
Downloader
. У этого класса имеется слот
onResult
, который в свою очередь отвечает за обработку результата ответа
QNetworkAccessManager
.void Downloader::onResult(QNetworkReply *reply) { // Если в процессе получения данных произошла ошибка if(reply->error()){ // Сообщаем об этом и показываем информацию об ошибках qDebug() << "ERROR"; // Здесь получаем один из enum NetworkError, то есть код ошибки qDebug() << reply->error(); } else { // ToDo something } }