Михаиллл
Михаиллл14 мая 2020 г. 8:41

Как через POST запрос отправить файл

Добрый день.
Пытаюсь в json запихнуть картинку и отправить, но получаю ошибку

413 Entity too large

Скажите пожалуйста, как все же отправить картинку POST запросом?

void AppCore::slotApiRequest(QByteArray data)
{
    QNetworkRequest request;
    request.setHeader( QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded" );
    request.setUrl(QUrl(urlServerForRequest));
    request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); //разрешает перенаправление
    request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");
    request.setHeader(QNetworkRequest::ContentLengthHeader,QByteArray::number(data.size()));
    myApiQuery.post(request, data);
}

void AppCore::addCategory(QString nameCategory, QString fileName)
{
    fileName = fileName.remove("file:///");
    //qDebug()<<nameCategory<<fileName;
    QImage myImage(fileName);

    QByteArray bArray;
    QBuffer buffer(&bArray);
    buffer.open(QIODevice::WriteOnly);
    myImage.save(&buffer, "BMP");
    QString imageString("data:image/bmp;base64,");
    imageString.append(QString::fromLatin1(bArray.toBase64().data()));
    //qDebug()<<imageString;

    QJsonObject jObj = QJsonObject{{"nameCategory", nameCategory}, {"image", imageString}};
    //QJsonObject jObj = QJsonObject{{"nameCategory", nameCategory}, {"image", fileName}};
    QJsonDocument doc = QJsonDocument(jObj);
    QByteArray arrayJson;
    QString strJson(doc.toJson(QJsonDocument::Compact));
    arrayJson += strJson;

    urlServerForRequest= urlServer + "addCategory";
    slotApiRequest(arrayJson);
}
Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Вам это нравится? Поделитесь в социальных сетях!

16
Evgenii Legotckoi
  • 14 мая 2020 г. 8:46

Добрый день.

Это вам не C++ код копать нужно, а сервер настраивать. Если на сервере nginx, то настройте максимальный размер запроса.
Он вас просто отпинывает из-за слишком большого тела запроса.

Вот для максимального размера в 2 мб

client_max_body_size 2m;
    Evgenii Legotckoi
    • 14 мая 2020 г. 8:52

    Ну или уменьшайте размер изображения до того, который пропустит сервер.

      Михаиллл
      • 14 мая 2020 г. 9:05

      Я использую QtWebApp. Вы случайно не знаете, как в нем настраивать?

        Evgenii Legotckoi
        • 14 мая 2020 г. 9:10

        Глянул документацию, там нужно колупать структуру HttpConnectionHandlerSettings

        В ней есть поля maxRequestSize и maxMultipartSize

        • maxRequestSize - размер тела запроса
        • maxMultipartSize - размера запроса для изображений и прочей медия ерунды

        Поищите, как установить maxMultipartSize больше, чем 1048576

        В каком конкретно месте это делать, я не знаю. Но думаю, что-то такое при инициализации нужно настраивать

          Михаиллл
          • 14 мая 2020 г. 9:32
          • (ред.)

          Нашел эти настройки в файле .ini
          Сделал так, но почему то все равно запрос не доходит, и узнал что размер моего запроса 51321 символов.
          Скажите пожалуйста, в чем еще могут быть трудности?

          [listener]
          ; host=192.168.0.100
          port=8080
          minThreads=4
          maxThreads=100
          cleanupInterval=60000
          readTimeout=60000
          maxRequestSize=10000000
          maxMultiPartSize=10000000
          
          

          И ошибок не выдает, ту ошибку выдало только один раз, в остальных предыдущих случаях все проходило так же без ошибок.

            Evgenii Legotckoi
            • 14 мая 2020 г. 10:05

            Не понял фразу

            И ошибок не выдает, ту ошибку выдало только один раз, в остальных предыдущих случаях все проходило так же без ошибок.

            То есть ошибок нет, но загрузить не получается?

            узнал что размер моего запроса 51321 символов.

            Символов или байт? в зависимости от кодировки символ может занимать большее количество байт, чем один.

            Также ещё поменяйте заголовок запроса так (что-то я не обратил внимания сразу, вы ведь изображение грузите)

            request.setHeader( QNetworkRequest::ContentTypeHeader, "multipart/form-data" );
            
              Михаиллл
              • 14 мая 2020 г. 10:43

              Верно, ошибок нет, но загрузить не получается.
              Размер я узнаю методос QByteArray::size и вероятней всего получаю количество символов.
              Попробовал поменять заголовок, но результат тот же.
              Может быть как то иначе файлы нужно подгружать?

                Evgenii Legotckoi
                • 15 мая 2020 г. 3:03

                Вы у себя в коде дважды используете

                request.setHeader( QNetworkRequest::ContentTypeHeader, "" );
                

                Попробуйте убрать тот, что с application/json

                  Михаиллл
                  • 15 мая 2020 г. 3:11

                  Сделал так

                      QNetworkRequest request;
                      //request.setHeader( QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded" );
                      request.setUrl(QUrl(urlServerForRequest));
                      request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); //разрешает перенаправление
                      request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");
                      //request.setHeader( QNetworkRequest::ContentTypeHeader, "multipart/form-data" );
                      request.setHeader(QNetworkRequest::ContentLengthHeader,QByteArray::number(data.size()));
                      qDebug()<<data.size();
                      myApiQuery.post(request, data);
                  

                  и получил в первый раз ошибку

                  "413 Entity too large\r\n"
                  

                  а больше ошибок не выдавало, при этом запрос не проходит.
                  так тоже не работает, но ошибок не выдает

                      QNetworkRequest request;
                      //request.setHeader( QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded" );
                      request.setUrl(QUrl(urlServerForRequest));
                      request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); //разрешает перенаправление
                      //request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");
                      request.setHeader( QNetworkRequest::ContentTypeHeader, "multipart/form-data" );
                      request.setHeader(QNetworkRequest::ContentLengthHeader,QByteArray::number(data.size()));
                      qDebug()<<data.size();
                      myApiQuery.post(request, data);
                  
                    Evgenii Legotckoi
                    • 15 мая 2020 г. 3:17

                    всё... вот теперь у меня идеи закончились (((

                    Могу только предложить покопаться в исходника QtWebApp, посмотреть в каком случае появляется та ошибка и попытаться её исправить.

                    Ещё возможно, что саму пересылку изображения нужно как-то иначе паковать. То есть не через "data:image/bmp;base64,"

                      Михаиллл
                      • 15 мая 2020 г. 3:57
                      • (ред.)

                      Тут удобно смотреть и искать.
                      Ошибку выдает эта функция. Почему-то срабатывает условие (30 стр) "currentRequest->getStatus()==HttpRequest::abort"

                      void HttpConnectionHandler::read()
                       {
                           // The loop adds support for HTTP pipelinig
                           while (socket->bytesAvailable())
                           {
                               #ifdef SUPERVERBOSE
                                   qDebug("HttpConnectionHandler (%p): read input",static_cast<void*>(this));
                               #endif
                      
                               // Create new HttpRequest object if necessary
                               if (!currentRequest)
                               {
                                   currentRequest=new HttpRequest(settings);
                               }
                      
                               // Collect data for the request object
                               while (socket->bytesAvailable() && currentRequest->getStatus()!=HttpRequest::complete && currentRequest->getStatus()!=HttpRequest::abort)
                               {
                                   currentRequest->readFromSocket(socket);
                                   if (currentRequest->getStatus()==HttpRequest::waitForBody)
                                   {
                                       // Restart timer for read timeout, otherwise it would
                                       // expire during large file uploads.
                                       int readTimeout=settings->value("readTimeout",10000).toInt();
                                       readTimer.start(readTimeout);
                                   }
                               }
                      
                               // If the request is aborted, return error message and close the connection
                               if (currentRequest->getStatus()==HttpRequest::abort)
                               {
                                   socket->write("HTTP/1.1 413 entity too large\r\nConnection: close\r\n\r\n413 Entity too large\r\n");
                                   while(socket->bytesToWrite()) socket->waitForBytesWritten();
                                   socket->disconnectFromHost();
                                   delete currentRequest;
                                   currentRequest=nullptr;
                                   return;
                               }
                      
                               // If the request is complete, let the request mapper dispatch it
                               if (currentRequest->getStatus()==HttpRequest::complete)
                               {
                                   readTimer.stop();
                                   qDebug("HttpConnectionHandler (%p): received request",static_cast<void*>(this));
                      
                                   // Copy the Connection:close header to the response
                                   HttpResponse response(socket);
                                   bool closeConnection=QString::compare(currentRequest->getHeader("Connection"),"close",Qt::CaseInsensitive)==0;
                                   if (closeConnection)
                                   {
                                       response.setHeader("Connection","close");
                                   }
                      
                                   // In case of HTTP 1.0 protocol add the Connection:close header.
                                   // This ensures that the HttpResponse does not activate chunked mode, which is not spported by HTTP 1.0.
                                   else
                                   {
                                       bool http1_0=QString::compare(currentRequest->getVersion(),"HTTP/1.0",Qt::CaseInsensitive)==0;
                                       if (http1_0)
                                       {
                                           closeConnection=true;
                                           response.setHeader("Connection","close");
                                       }
                                   }
                      
                                   // Call the request mapper
                                   try
                                   {
                                       requestHandler->service(*currentRequest, response);
                                   }
                                   catch (...)
                                   {
                                       qCritical("HttpConnectionHandler (%p): An uncatched exception occured in the request handler",
                                                 static_cast<void*>(this));
                                   }
                      
                                   // Finalize sending the response if not already done
                                   if (!response.hasSentLastPart())
                                   {
                                       response.write(QByteArray(),true);
                                   }
                      
                                   qDebug("HttpConnectionHandler (%p): finished request",static_cast<void*>(this));
                      
                                   // Find out whether the connection must be closed
                                   if (!closeConnection)
                                   {
                                       // Maybe the request handler or mapper added a Connection:close header in the meantime
                                       bool closeResponse=QString::compare(response.getHeaders().value("Connection"),"close",Qt::CaseInsensitive)==0;
                                       if (closeResponse==true)
                                       {
                                           closeConnection=true;
                                       }
                                       else
                                       {
                                           // If we have no Content-Length header and did not use chunked mode, then we have to close the
                                           // connection to tell the HTTP client that the end of the response has been reached.
                                           bool hasContentLength=response.getHeaders().contains("Content-Length");
                                           if (!hasContentLength)
                                           {
                                               bool hasChunkedMode=QString::compare(response.getHeaders().value("Transfer-Encoding"),"chunked",Qt::CaseInsensitive)==0;
                                               if (!hasChunkedMode)
                                               {
                                                   closeConnection=true;
                                               }
                                           }
                                       }
                                   }
                      
                                   // Close the connection or prepare for the next request on the same connection.
                                   if (closeConnection)
                                   {
                                       while(socket->bytesToWrite()) socket->waitForBytesWritten();
                                       socket->disconnectFromHost();
                                   }
                                   else
                                   {
                                       // Start timer for next request
                                       int readTimeout=settings->value("readTimeout",10000).toInt();
                                       readTimer.start(readTimeout);
                                   }
                                   delete currentRequest;
                                   currentRequest=nullptr;
                               }
                           }
                       }
                      
                        Evgenii Legotckoi
                        • 15 мая 2020 г. 4:07
                        • Ответ был помечен как решение.

                        Мне ещё одна мысль в голову пришла, попробуйте связаться с автором библиотеки.
                        Вроде адекватный малый, я ему в 2016-м году исправление посылал. Он быстро среагировал.
                        Может у него есть готовый пример для загрузки файла. Естественно писать ему нужно на английском.

                          Михаиллл
                          • 15 мая 2020 г. 4:22

                          Написал ему. А как долго он вам отвечал? И как думаете, в какую сторону кода стоит копать?

                            Evgenii Legotckoi
                            • 15 мая 2020 г. 4:26

                            Тогда он мне ответил вроде бы в течение пары дней.
                            Вполне возможно, что нужно правильно сформировать данные с изображением.
                            Также всё-таки может быть проблема со стороны сервера...
                            Но у меня не было никогда задачи делать загрузку изображения через QNetworkAccessManager и тем более делать этот на сервер с QtWebApp.
                            Поэтому я только предполагал возможные проблемы, но видимо там есть какой-то нюанс, который я не могу понять.

                              Михаиллл
                              • 16 мая 2020 г. 4:23

                              Скажите пожалуйста, как с помощью отладчика понять, загружен ли .ini файл?

                                Михаиллл
                                • 16 мая 2020 г. 5:11
                                • (ред.)

                                Оказалось в startup.cpp нужно в

                                /** Name of this application */
                                #define APPNAME "HttpSerwerQtWebAppGameTamada"
                                

                                не забыть поменять имя, тогда инициализация проходит и сервер нормально работает

                                  Комментарии

                                  Только авторизованные пользователи могут публиковать комментарии.
                                  Пожалуйста, авторизуйтесь или зарегистрируйтесь
                                  AD

                                  C++ - Тест 004. Указатели, Массивы и Циклы

                                  • Результат:50баллов,
                                  • Очки рейтинга-4
                                  m
                                  • molni99
                                  • 26 октября 2024 г. 8:37

                                  C++ - Тест 004. Указатели, Массивы и Циклы

                                  • Результат:80баллов,
                                  • Очки рейтинга4
                                  m
                                  • molni99
                                  • 26 октября 2024 г. 8:29

                                  C++ - Тест 004. Указатели, Массивы и Циклы

                                  • Результат:20баллов,
                                  • Очки рейтинга-10
                                  Последние комментарии
                                  i
                                  innorwall12 ноября 2024 г. 6:12
                                  Django - Урок 055. Как написать функционал auto populate field Freckles because of several brand names retin a, atralin buy generic priligy
                                  i
                                  innorwall12 ноября 2024 г. 2:23
                                  QML - Урок 035. Использование перечислений в QML без C++ priligy cvs 24 Together with antibiotics such as amphotericin B 10, griseofulvin 11 and streptomycin 12, chloramphenicol 9 is in the World Health Organisation s List of Essential Medici…
                                  i
                                  innorwall11 ноября 2024 г. 23:50
                                  Qt/C++ - Урок 052. Кастомизация Qt Аудио плеера в стиле AIMP It decreases stress, supports hormone balance, and regulates and increases blood flow to the reproductive organs buy priligy online safe Promising data were reported in a PDX model re…
                                  i
                                  innorwall11 ноября 2024 г. 22:19
                                  Алгоритм сортировки кучей The role of raloxifene in preventing breast cancer priligy precio
                                  i
                                  innorwall11 ноября 2024 г. 21:55
                                  PyQt5 - Урок 006. Работа с QTableWidget buy priligy 60 mg 53 have been reported by Javanovic Santa et al
                                  Сейчас обсуждают на форуме
                                  i
                                  innorwall12 ноября 2024 г. 4:56
                                  добавить qlineseries в функции buy priligy senior brother Chu He, whom he had known for many years
                                  i
                                  innorwall11 ноября 2024 г. 18:55
                                  Всё ещё разбираюсь с кешем. priligy walgreens levitra dulcolax carbs The third ring was found to be made up of ultra relativistic electrons, which are also present in both the outer and inner rings
                                  9
                                  9Anonim25 октября 2024 г. 16:10
                                  Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…
                                  ИМ
                                  Игорь Максимов3 октября 2024 г. 11:05
                                  Реализация навигации по разделам Спасибо Евгений!

                                  Следите за нами в социальных сетях