Wifi Shield client HTTP POST binary data not working

I'm working on a project where I want to upload a picture taken with the Adafruit TTL camera to a webserver via the Wifi connection.

The camera: https://learn.adafruit.com/ttl-serial-camera/using-the-camera

I have followed this short tutorial to upload the picture and modified where necessary: https://www.openhomeautomation.net/wireless-camera/

Connecting to the wifi network and posting data (parameters like a=1&b=2) to the webserver works fine. Taking pictures with the cam also works. But uploading a 3.5kB picture doesn't seem to work. I tested with several number of bytes 16, 32 and 64 and with different delays 0, 100, 300ms between writes. (see code)

Anyone has advice on this? Or can provide example code?

My setup: Arduino Uno Arduino Wifi Shield TTL camera

Code to post the image:

uint16_t jpglen = cam.frameLength();
  Serial.print(F("Storing "));
  Serial.print(jpglen, DEC);
  Serial.print(F(" byte image."));
  
  // Prepare request
  String start_request = "";
  String end_request = "";
  start_request = start_request + "\n" + "--AaB03x" + "\n" + "Content-Disposition: form-data; name=\"picture\"; filename=\"CAM.JPG\"" + "\n" + "Content-Type: image/jpeg" + "\n" + "Content-Transfer-Encoding: binary" + "\n" + "\n";  
  end_request = end_request + "\n" + "--AaB03x--" + "\n";
  
  uint16_t extra_length;
  extra_length = start_request.length() + end_request.length();
  Serial.println(F("Extra length:"));
  Serial.println(extra_length);
  
  uint16_t len = jpglen + extra_length;
  
   Serial.println(F("Content-Type: multipart/form-data; boundary=AaB03x"));
   Serial.print(F("Content-Length: "));
   Serial.println(len);
   Serial.print(start_request);
   Serial.print(F("binary data"));
   Serial.print(end_request);

  Serial.println(F("Starting connection to server..."));
  client.connect(server,80);
  
  // Connect to the server, please change your IP address !
  if (client.connected()) {
      Serial.println(F("Connected !"));
      client.println(F("POST /api/upload.php HTTP/1.1"));
      client.println(F("Host: www.****.com"));
      client.println(F("Content-Type: multipart/form-data; boundary=AaB03x"));
      client.print(F("Content-Length: "));
      client.print(len);
  ///    client.print(start_request);
     client.print("\r\n--AaB03x\r\nContent-Disposition: form-data; name=\"picture\"; filename=\"CAM.JPG\"\r\nContent-Type: image/jpeg\r\nContent-Transfer-Encoding: binary\r\n\r\n");       
      // Read all the data up to # bytes!
      byte wCount = 0; // For counting # of writes
      while (jpglen > 0) {
        
        uint8_t *buffer;
        uint8_t bytesToRead = min(16, jpglen); // change 32 to 64 for a speedup but may not work with all setups!
        
        buffer = cam.readPicture(bytesToRead);
        client.write(buffer, bytesToRead);
    
        if(++wCount >= 64) { // Every 2K, give a little feedback so it doesn't appear locked up
          Serial.print('.');
          wCount = 0;
        }
        jpglen -= bytesToRead; 
        delay(100);
      }
      
      //client.print(end_request);
      client.print("\r\n--AaB03x--\r\n");
      client.println();
      
  Serial.println(F("Transmission over"));
  }

Upload code (upload.php) on webserver is never called (I check via fwrite in the file).

$target_path = "uploads/";
$target_path = $target_path . basename( $_FILES['picture']['name']);
if(move_uploaded_file($_FILES['picture']['tmp_name'], $target_path)) {
 echo "The file ". basename( $_FILES['picture']['name'])." has been uploaded";

}
else {
 echo "There was an error uploading the file, please try again!";
}

Thank you for your time reading this :-)

After a few more hours of debugging and checking my raw webserver logs I noticed that the Content-Length parameter was not correct.

If anyone encounters the same problem I can give you advice.

I've faced the same problem for several weeks. Could you explain more about how incorrect the Content-Length parameter is and what the correct one needs to be.

Thank you very much for your help.

Thanks for posting your problem and solution. This was very helpful as it confirmed that my GET message appears to be in the correct format with the exception of the check for client.connected(). I was using that but I would frequently lose connection so I used client.connect() as my opening conditional check (please see code below).

If I understand this correctly, a get message should be the same but does not need the message body at the end as I should just be modifying the URL that is passed, right?

My code for sending the GET message is below. I am using the Arduino WiFi Shield with an Arduino UNO but my .php file is not receiving the message. I believe the .php file is correct as I am able to validate using the curl command.

Code:

if (client.connect(server,80)) {

client.print( "GET /arduino-test1/arduino-iot-test-july2015/addsensordata.php?"); client.print("temp1="); client.print( currentTemp ); client.print("&"); client.print("photo1="); client.print( currentTemp ); client.print( " HTTP/1.1\r\n"); client.print( "Host: www.*****.org\r\n" ); client.print( "Content-Type: application/x-www-form-urlencoded\r\n" ); client.print( "Connection: close\r\n\r\n" );

client.stop(); } else { Serial.println("Disconnected"); }

If I observe the message using the serial port, it looks like the following.

GET /arduino-test1/arduino-iot-test-july2015/addsensordata.php?temp1=26.06&photo1=26.06 HTTP/1.1 Host: www.*****.org Content-Type: application/x-www-form-urlencoded Connection: close

Thanks for any help that you could provide..