Почему HTTP POST на Arduino не отправляет большие файлы

#http #post #arduino-uno

#http #Публикация #arduino-uno

Вопрос:

Я пытаюсь отправить большой файл на сервер, используя HTTP POST. Я могу отправлять файлы размером 4 КБ или меньше, но когда я пытаюсь отправить файл размером 1,5 МБ, кажется, что время ожидания истекло. Сервер отключается без отправки данных

Кто-нибудь знает, как это исправить?

Код: void readdata() {

   //Variables for WiFi Shield
  char ssid[] = "Example";           //your network SSID (name)
  char pass[] = "Example1";           
  char server[] = "http://example.com";

  while (status != WL_CONNECTED) {
    Serial.print(F("Attempting to connect to SSID: "));
    Serial.println(ssid);

    status = WiFi.begin(ssid, pass);

    // wait 1 second for connection:
    delay(1000);
  }
  Serial.println(F("Connected to wifi"));
 // #endif

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println(F("WiFi shield not present"));
    // don't continue:
   while (true);
  }
logfile=SD.open("LOG0038.CSV");
filesize=logfile.size();
  logfile.close();

  int fileLength = 0;
  fileLength = 137   filesize   40;
  Serial.println(filesize);

  Serial.println(F("nStarting connection to server..."));
  Serial.println(server);
  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println(F("connected to server"));

    // Make a HTTP request:

  client.setTimeout(Time);
  client.print(F("POST /uploadf HTTP/1.1rn"));
  client.print(F("Host: example.comrn"));
  client.print(F("User-Agent: Frank/1.0rn"));
  client.print(F("Accept-Encoding: gzip, deflatern"));
  client.print(F("Accept: */*rn"));
  client.print(F("Connection: keep-alivern"));
  client.print(F("Content-Length: "));
  client.print(fileLength);
  client.print(F("rn"));
  client.print(F("Content-Type: multipart/form-data; boundary=710ff0c6cf2d4c73b12db64cab12e58crn"));
  client.print(F("rn"));
  client.print(F("--710ff0c6cf2d4c73b12db64cab12e58crnContent-Disposition: form-data; name="file"; filename=""));
  client.print("1000LOG0032.CSV");
  client.print(F("""));
  client.print(F("rn"));
  client.print(F("Content-Type: text/plainrnrn"));
  logfile=SD.open("LOG0038.CSV");
  while(logfile.available()){
    while(logfile.position() < logfile.size()){
      String dataBuff = logfile.readStringUntil('n');
      client.print(dataBuff);
     // Serial.println(dataBuff);
      client.print("n");
    }
  }
  client.print(F("rn--710ff0c6cf2d4c73b12db64cab12e58c--rn"));
  //client.flush();
  }

  while(client.connected()){
    while (client.available()amp;amp; status==WL_CONNECTED) {
      char c = client.read();
     Serial.write(c);
   }
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.print(F("rn"));
    Serial.println(F("disconnecting from server."));
 //   client.flush();
    client.stop();

  } 
 logfile.close();
 while (true);
  }
  

Комментарии:

1. Сервер закрывает соединение? Вы проверяли, есть ли ограничение на размер HTTP post на вашем сервере

2. Я проверил сервер, и у него нет ограничений на размер HTTP POST — похоже, что arduino будет отправлять только 20 КБ данных за раз

Ответ №1:

Возможно, это не настоящий ответ, но, к сожалению, у меня нет необходимой репутации, чтобы написать это в качестве комментария.

Я ничего не знаю об arduino, но всякий раз, когда вы работаете с POST, должна быть возможность ограничить max_post_size. В базовой настройке LAMP это обычно находится в .httaccess.

Я надеюсь, что это поможет вам в устранении неполадок.

Ответ №2:

Можно отправить запрос POST с полями данных, дополненными двоичными данными, как показано в приведенном ниже коде. Представленный код был создан для отправки запроса POST в репозиторий Dataverse (dataverse.org ), однако, может быть легко адаптирован к любому другому запросу POST. И последнее замечание: приведенный ниже код оптимизирован для микропроцессоров Xtensa LX6 / 7 от Tensilica по сравнению с ESP32.

Полный код можно найти здесь:

https://github.com/aeonSolutions/openScienceResearch-Smart-DAQ-Device-able-to-Upload-Live-Experimental-Sensor-Data-to-a-Data-Repo

 // *********************************************************
//            Upload Dataset to Harvard's Dataverse
// *********************************************************
void UploadToDataverse() {
  //Check WiFi connection status
  if(WiFi.status() != WL_CONNECTED){
    mserial.printStrln("WiFi Disconnected");
    if (connect2WIFInetowrk()){
      UploadToDataverse();
    }
  }
  // Start sending dataset file
  File datasetFile = FFat.open("/" EXPERIMENTAL_DATA_FILENAME, FILE_READ);
  if (!datasetFile){
    mserial.printStrln("Dataset file not found");
    return;
  }
    
  String boundary = "7MA4YWxkTrZu0gW";
  String contentType = "text/csv";
  // DATASET_REPOSITORY_URL = "/api/files/:persistentId/replace?persistentId="  PERSISTENT_ID;
  DATASET_REPOSITORY_URL =  "/api/datasets/:persistentId/add?persistentId=" PERSISTENT_ID;
  
  String datasetFileName = datasetFile.name();
  String datasetFileSize = String(datasetFile.size());
  mserial.printStrln("Dataset File Details:");
  mserial.printStrln("Filename:"   datasetFileName);
  mserial.printStrln("size (bytes): "  datasetFileSize);
  mserial.printStrln("");
    
  WiFiClientSecure client;

  int str_len = SERVER_URL.length()   1; // Length (with one extra character for the null terminator)
  char SERVER_URL_char [str_len];    // Prepare the character array (the buffer) 
  SERVER_URL.toCharArray(SERVER_URL_char, str_len);    // Copy it over 
    
  client.stop();
  client.setCACert(HARVARD_ROOT_CA_RSA_SHA1);
  if (!client.connect(SERVER_URL_char, SERVER_PORT)) {
      mserial.printStrln("Cloud server URL connection FAILED!");
      mserial.printStrln(SERVER_URL_char);
      int server_status = client.connected();
      mserial.printStrln("Server status code: "   String(server_status));
      return;
  }
  mserial.printStrln("Connected to the dataverse of Harvard University"); 
  mserial.printStrln("");
  // We now create a URI for the request
  mserial.printStr("Requesting URL: ");
    mserial.printStrln(DATASET_REPOSITORY_URL);

  // Make a HTTP request and add HTTP headers    
  // post header
  String postHeader = "POST "   DATASET_REPOSITORY_URL   " HTTP/1.1rn";
  postHeader  = "Host: "   SERVER_URL   ":"   String(SERVER_PORT)   "rn";
  postHeader  = "X-Dataverse-key: "   API_TOKEN   "rn";
  postHeader  = "Content-Type: multipart/form-data; boundary="   boundary   "rn";
  postHeader  = "Accept: text/html,application/xhtml xml,application/xml;q=0.9,*/*;q=0.8rn";
  postHeader  = "Accept-Encoding: gzip,deflatern";
  postHeader  = "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7rn";
  postHeader  = "User-Agent: AeonLabs LDAD Smart DAQ devicern";
  postHeader  = "Keep-Alive: 300rn";
  postHeader  = "Connection: keep-alivern";
  postHeader  = "Accept-Language: en-usrn";

  // jsonData header
  String jsonData = "{"description":"LIVE Experimental data upload from LDAD Smart 12bit DAQ ","categories":["Data"], "restrict":"false", "tabIngest":"false"}";     
  String jsonDataHeader = "--"   boundary   "rn";
  jsonDataHeader  = "Content-Disposition: form-data; name="jsonData"rnrn";
  jsonDataHeader  = jsonData "rn";

  // dataset header
  String datasetHead = "--"   boundary   "rn";
  datasetHead  = "Content-Disposition: form-data; name="file"; filename=""   datasetFileName   ""rn";
  datasetHead  = "Content-Type: "   contentType   "rnrn";

  // request tail
  String tail = "rn--"   boundary   "--rnrn";

  // content length
  int contentLength = jsonDataHeader.length()   datasetHead.length()   datasetFile.size()   tail.length();
  postHeader  = "Content-Length: "   String(contentLength, DEC)   "nn";
  
  // send post header
  int postHeader_len=postHeader.length()   1; 
  char charBuf0[postHeader_len];
  postHeader.toCharArray(charBuf0, postHeader_len);
  client.print(charBuf0);
  mserial.printStr(charBuf0);

  // send key header
  char charBufKey[jsonDataHeader.length()   1];
  jsonDataHeader.toCharArray(charBufKey, jsonDataHeader.length()   1);
  client.print(charBufKey);
  mserial.printStr(charBufKey);

  // send request buffer
  char charBuf1[datasetHead.length()   1];
  datasetHead.toCharArray(charBuf1, datasetHead.length()   1);
  client.print(charBuf1);
  mserial.printStr(charBuf1);

  // create buffer
  const int bufSize = 2048;
  byte clientBuf[bufSize];
  int clientCount = 0;

  while (datasetFile.available()) {
    clientBuf[clientCount] = datasetFile.read();
    clientCount  ;
    if (clientCount > (bufSize - 1)) {
        client.write((const uint8_t *)clientBuf, bufSize);
        clientCount = 0;
    }
  }

  datasetFile.close();
    
  if (clientCount > 0) {
      client.write((const uint8_t *)clientBuf, clientCount);
      mserial.printStrln("[binary data]");
  }

  // send tail
  char charBuf3[tail.length()   1];
    tail.toCharArray(charBuf3, tail.length()   1);
    client.print(charBuf3);
  mserial.printStr(charBuf3);



  // Read all the lines of the reply from server and print them to mserial
    mserial.printStrln("");
    mserial.printStrln("Response Headers:");
  String responseHeaders = "";

  while (client.connected()) {
    // mserial.printStrln("while client connected");
    responseHeaders = client.readStringUntil('n');
    mserial.printStrln(responseHeaders);
    if (responseHeaders == "r") {
      mserial.printStrln("======   end of headers ======");
      break;
    }
  }

  String responseContent = client.readStringUntil('n');
  mserial.printStrln("Harvard University's Dataverse reply was:");
  mserial.printStrln("==========");
  mserial.printStrln(responseContent);
  mserial.printStrln("==========");
  mserial.printStrln("closing connection");
  client.stop();
  }