Post image file to database from esp8266 - tcp

I want to post image files of size around 15Kb, form my esp8266 based prototype to a non-sql database . I could post the json files of size less than 1Kb, But the http post fails for size grater than 1460 bytes.
HTTPClient http;
if( http.begin(myurl) ){
delay(1000);
char *auth = authString;
http.setAuthorization(auth);
http.addHeader("Content-Type","application/json", false, true);
int err = http.POST(largedata);
Serial1.print("HTTP Post reutrns : ");Serial1.println(err);
}

Related

PHPmailer - Add pdf file as attachment doesn't work

My Goal:
Use AddStringAttachment() to send a auto-generated base64 string as a .pdf file to another email address.
Coding Environment:
I'm working on WordPress with a ajax call passing a base64 string to the server. The size of the string is usually around 30kbs, it can be guaranteed not exceeding over 50kbs. I have MAX_EXECUTION_TIME 120s.
What I've Been Working Through:
I succeeded:
Sending plain text body
Sending a small .txt file
I failed:
Sending base64 string using AddStringAttachment(). The server returns me a 504 Gateway Time-out error most of time, even if $mail->send() function passes through, I can only receive a corrupt .pdf file with 10kbs bigger than original size.
Sending a already exist .pdf file with AddAttachment(), The server also returns me a 504 Gateway Time-out error, and I also get a warning like Resource interpreted as Document but transferred with MIME type application/pdf
My Code:
function sendPdf() {
$mail = new PHPMailer(true);
//Server settings
$mail->SMTPDebug = 2; // Enable verbose debug output
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'smtp.hostinger.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'janice#popper.ga'; // SMTP username
$mail->Password = 'secret'; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 587; // TCP port to connect to
//Recipient
$mail->SetFrom('janice#popper.ga');
$mail->AddAddress( 'xxxxxxxx#gmail.com' );
$pdf_base64 = $_POST[pdfString];
//Content
$mail->isHTML(true); // Set email format to HTML
$mail->Subject= ' New Application Form ';
$mail->Body= ' New Application Form From WordPress site ';
//Attachment
//$mail->AddStringAttachment($pdf_base64, $_POST[clientName].'_Application.pdf', 'base64', 'application/pdf');
//$mail->AddAttachment(dirname(__FILE__)."/Qian_Zhong_Application.pdf", 'Qian_Zhong_Application.pdf');
$error = '';
if(!$mail->send()){
$error = 'Mail error: '.$mail->ErrorInfo;
echo $error;
}else{
echo 'Message has been sent.';
}
exit; // This is required to end AJAX requests properly.
}
The data you pass in to addStringAttachment should be raw binary, not encoded in any way, as PHPMailer will take care of that for you. It will also set the encoding and MIME type from the filename you provide, so you do not need to set them manually.
Using a debugger would allow you to watch the script as it runs so you would be able to see exactly what it’s having trouble with. Any error 500s will cause errors to be logged in your web server logs and will usually provide more info.
I would also recommend against using $_POST[clientName] like that without any filtering or validation - you should never trust user input like that.

How to build HTTP Response with ESP8266 and Arduino

I want to toggle some LEDs with my Android device. These LEDs are connected to the digital Pins of my Arduino which is also connected to a ESP8266. Now, my ESP8266 is defined as an AccessPoint and my Tablet can send HTTP requests (e.g. http://192.168.4.1:80/?pin=11).
I found the code here http://allaboutee.com/2015/01/20/esp8266-android-application-for-arduino-pin-control/
It works fine but my question is which HTTP header fields should be used? In this code he used some (e.g. Content-Length) but there are so much more possible (Date, Server, Content-Language,...).
Are these fields optional or which of these have to be used to build the right response?
Here is the piece of code I do not understand:
void sendHTTPResponse(int connectionId, String content)
{
String httpResponse;
String httpHeader;
httpHeader = "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n";
httpHeader += "Content-Length: ";
httpHeader += content.length();
httpHeader += "\r\n";
httpHeader +="Connection: close\r\n\r\n";
httpResponse = httpHeader + content + " ";
sendCIPData(connectionId,httpResponse);
}
It largely depends on the client (i.e. consumer) which fields are required and which are mandatory.
The only one that is always required is "HTTP/1.1 200 OK". Of course you need to replace that status code if you're not sending an OK message.

server.args() ESP8266 Arduino

I am using the ESP8266 with Arduino IDE and have set up a server at port 200 . The IP is also defined as the same as 192.168.1.100.
ESP8266WebServer server(200);
IPAddress ip(192, 168, 1, 100); //Node static IP
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
server.on("/parseIFTTT", parseIFTTT);
void parseIFTTT() {
String message;
message += server.args();
message += "\n";
for (uint8_t i = 0; i < server.args(); i++) {
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
Serial.println(message);
Serial.println(server.argName(0));
Serial.println(server.arg(0));
server.send(200, "text/plain", "Success " + message);
}
is done to route the parseIFTTT request to this parseIFTTT() method.
I have done port forwarding and using the duckdns to access this server from outside.
This is my duckdns address
http://xxxxxx.duckdns.org:200/parseIFTTT
When I make a POST using a POSTMAN tool with content type as text/plain , the body contents are shown in the serial monitor as
plain
--body contents--
But when the same request is made from IFTTT the serial monitor shows nothing but plain as empty .Initially I felt the issue is with IFTTT.
But that is not the issue as when I use the WiFiWebServer example in the arduino , using the following code
String req = client.readString();
Serial.println(req);
client.flush();
I see the data from IFTTT as :
POST /parseIFTTT HTTP/1.1
Content-type: text/plain
host: xxxxxx.duckdns.org:200
content-length: 27
x-newrelic-id: XAMGV15QGwQJVllRDgQ=
x-newrelic-transaction: PxQFA1NbAQQJVwJWA1dSB0YdUFIOFQZOEgEPVA5ZBFYGXAwECFgFAFcUG0MHUwoLBAcDAxVs
Connection: close
{"value":"test data from IFTTT"}
So I believe I am doing something wrong with the server.args(). I am under the impression that server.args() should give the body contents used in the POST whether contentType is text/plain or x-www-form-urlencoded.
Am I doing something wrong or with the server.args() can't we get the body data from the POST request ?
There are a few 'gotchas' in the ESP8266WebServer's implementation. I have found the body shows up in the
server.arg("plain")
but only if the class cannot find any key value pairs. The ESP8266WebServer will look for an '=' and only if it cannot find one will it put the body in the "plain" arg.
This arg will contain the full body so you will have to parse the JSON yourself. I have found ArduinoJson to be a very easy to use library to do so.
Short example:
void handleRequest() {
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(server.arg("plain"));
root.printTo(Serial);
}
On a sidenote. If you are testing with a POSTMAN like tool, do not forget to set the 'Content-length'. ESP8266WebServer will treat your body as empty (or of a different length) if it does not correspond with this header value.
Hope this answers your question.
Thanks the code solution for " how to get the IP client using ESP8266WebServer" is :
// HTTP Request Path, IRIA Entry Form
server.on("/", [](){
// As sending the form as a response to the client
server.send(200, "text/html",login_CASA);
String addy = server.client().remoteIP().toString();
Serial.println(addy);
});

uploading files using httpSendRequest c++

I am trying to send a file to HTTP server via POST request (c++ and winapi), steps:
// Read file into "buff" and file size into "buffSize"
....
....
....
HINTERNET internetRoot;
HINTERNET httpSession;
HINTERNET httpRequest;
internetRoot = InternetOpen(agent_info, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, NULL);
//Connecting to the http server
httpSession = InternetConnect(internetRoot, IP,PORT_NUMBER, NULL, NULL, INTERNET_SERVICE_HTTP, NULL, NULL);
//Creating a new HTTP POST request to the default resource on the server
httpRequest = HttpOpenRequest(httpSession, TEXT("POST"), TEXT("/Post.aspx"), NULL, NULL, NULL, INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, NULL);
//Send POST request
HttpSendRequest(httpRequest, NULL, NULL, buff, buffSize);
//Closing handles...
In server I am recieving the file using this code (asp.net)
Stream httpStream;
try
{
httpStream = request.RequestContext.HttpContext.Request.InputStream;
}
catch (HttpException)
{
return;
}
byte[] tmp = new byte[httpStream.Length];
int bytesRead = httpStream.Read(tmp, 0, 1024 * 1024);
int totalBytesRead = bytesRead;
while (bytesRead > 0)
{
bytesRead = httpStream.Read(tmp, totalBytesRead, 1024 * 1024);
totalBytesRead += bytesRead;
}
httpStream.Close();
httpStream.Dispose();
//Save "tmp" to file...
I can send large files on local server (visual studio asp server), but I cannot send files over 1 MB to internet server. (HttpOpenRequest is failing)
is there a better way to upload files?
Caveat: My Wininet is very rusty these days.
I wonder whether you ought to be setting the "Content-Length" header yourself. Your code seems to assume that either a) you are making a HTTP/1.0 request or b) that HttpSendRequest will add the header for your (which I don't think it does).
Either way without the server being told how big the incoming request is the default configuration of IIS will reject it if it can't determine the request size itself quickly.
My guess is if you use the lpszHeaders and dwHeadersLength parameters of the HttpSendRequest function to include the appropriate "Content-Length" header the problem will be resolved.
What error do you receive? I mean what does GetLastError() returns? If you send file 800KB then it works OK? I dont really see how because HttpOpenRequest does not know about size of the data.
Maybe it timeouts? But this would mean that HttpSendRequest actually fails. It might buffer all data but since size is huge, then it takes more time than timeout allows.
use following code to query current timeouts (in ms):
InternetQueryOption(h, INTERNET_OPTION_RECEIVE_TIMEOUT, &dwReceiveTimeOut, sizeof(dwReceiveTimeOut));
InternetQueryOption(h, INTERNET_OPTION_SEND_TIMEOUT, &dwSendTimeOut, sizeof(dwSendTimeOut));
and following to set new ones:
InternetSetOption(h, INTERNET_OPTION_RECEIVE_TIMEOUT, &dwNewReceiveTimeOut, sizeof(dwNewReceiveTimeOut));
InternetSetOption(h, INTERNET_OPTION_SEND_TIMEOUT, &dwNewSendTimeOut, sizeof(dwNewSendTimeOut));

Making a http POST request using Arduino

I am trying to post information to an API on a web project that I have created and hosted. I am not sure what the exact format is for the HTTP POST request. Every time I try I get HTTP 400 errors with the message that there is "an invalid verb".
Sample Code:
byte server[] = {"our IP"}
..
..
client(server, 80)
..
..
client.println("POST /Api/AddParking/3");
It connects to the IP address supplied without any problems, but all I get back in the above mentioned HTTP error code 400. I am not sure if I was supposed to include a HTTP version after my POST or and Content-Length or any other information.
The original question is already answered, but just for reference for people passing by via Google; here is a more complete example how to post data to a webserver with an Arduino:
IPAddress server(10,0,0,138);
String PostData = "someDataToPost";
if (client.connect(server, 80)) {
client.println("POST /Api/AddParking/3 HTTP/1.1");
client.println("Host: 10.0.0.138");
client.println("User-Agent: Arduino/1.0");
client.println("Connection: close");
client.print("Content-Length: ");
client.println(PostData.length());
client.println();
client.println(PostData);
}
Another option is using the HTTPClient.h (for the arduino IDE on adafruit's ESP32 feather), which handles https with no effort it seems. I'm including JSON payload also and can successfully send an IFTTT webhook.
HTTPClient http;
String url="https://<IPaddress>/testurl";
String jsondata=(<properly escaped json data here>);
http.begin(url);
http.addHeader("Content-Type", "Content-Type: application/json");
int httpResponseCode = http.POST(jsondata); //Send the actual POST request
if(httpResponseCode>0){
String response = http.getString(); //Get the response to the request
Serial.println(httpResponseCode); //Print return code
Serial.println(response); //Print request answer
} else {
Serial.print("Error on sending POST: ");
Serial.println(httpResponseCode);
http.end();
}
Sending hand-crafted HTTP packets can be a bit tricky because they are extremely picky about the format used. I highly recommend reading through the HTTP protocol if you have the time because it explains the syntax and fields required. In particular you should look at section 5 "Request".
With regards to your code, you do need to specify the HTTP version after the POST URI and I believe you also need to specify the "Host" header. On top of that you need to be sure to have a carriage-return line-feed (CRLF) at the end of each line. So, your packet should look something like:
POST /Api/AddParking/3 HTTP/1.1
Host: www.yourhost.com
Requests can be sent like that too
// Check if we are Connected.
if(WiFi.status()== WL_CONNECTED){ //Check WiFi connection status
HTTPClient http; //Declare object of class HTTPClient
http.begin("http://useotools.com/"); //Specify request destination
http.addHeader("Content-Type", "application/x-www-form-urlencoded", false, true);
int httpCode = http.POST("type=get_desire_data&"); //Send the request
Serial.println(httpCode); //Print HTTP return code
http.writeToStream(&Serial); // Print the response body
}

Resources