send both string and buffer using httplib with python to the server - php

How can I POST parameters with a file object to a URL using httplib in python web services.
Am using the following scripts:
import httplib
import urllib
params = urllib.urlencode({"#str1":"string1", "#str2":"string2", "#file":"/local/path/to/file/in/client/machine", "#action":"action.php" })
headers = {"Content-type":"application/pdf , text/*" }
conn = httplib.HTTPConnection("192.168.2.17")
conn.request("POST", "/SomeName/action.php", params, headers)
response = conn.getresponse()
print response.status, response.reason
data = response.read()
data
conn.close()
And I have the following output:
200
OK
<html>.....some html code </html>
I wrote some php code for save those string and the file in DB
My problem is that, Am only getting the file path as a sting but not my file.
May be I have to send the file object like,
file_obj = open("filename.txt","r")
conn.request("POST", "/SomeName/action.php", file_obj, headers)
But I want to send both strings and file. Any suggestions to solve this?
EDIT
I change my code as follows:
When i send a pdf file, by directly using httplib, to my server the file saves as BIN file.
def document_management_service(self,str_loc_file_path,*args):
locfile = open(str_loc_file_path,'rb').read()
host = "some.hostname.com"
selector = "/api/?task=create"
fields = [('docName','INVOICE'),('docNumber','DOC/3'),('cusName','name'),('cusNumber','C124'),('category','INVOICE'),('data','TIJO MRS,SOME/DATA/CONTENT,Blahblah,2584.00,blahblah'),('action','create')]
files = [('strfile','File.pdf',locfile)]
response = self.post_multipart(host, selector, fields, files)
print response
pass
def post_multipart(self,host, selector, fields, files):
content_type, body = self.encode_multipart_formdata(fields, files)
h = httplib.HTTP(host)
h.set_debuglevel(1)
h.putrequest('POST', selector)
h.putheader('content-type', content_type)
h.putheader('content-length', str(len(body)))
h.putheader('Host', host)
h.endheaders()
h.send(body)
errcode, errmsg, headers= h.getreply()
return h.file.read()
def encode_multipart_formdata(self, fields, files):
LIMIT = '----------lImIt_of_THE_fIle_eW_$'
CRLF = '\r\n'
L = []
for (key, value) in fields:
L.append('--' + LIMIT)
L.append('Content-Disposition: form-data; name="%s"' % key)
L.append('')
L.append(value)
for (key, filename, value) in files:
L.append('--' + LIMIT)
L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
L.append('Content-Type: %s' % self.get_content_type(filename))
L.append('')
L.append(value)
L.append('--' + LIMIT + '--')
L.append('')
body = CRLF.join(L)
content_type = 'multipart/form-data; boundary=%s' % LIMIT
return content_type, body
def get_content_type(self, filename):
return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
I have debug the request which shows as:
[('content-length', '4191'), ('accept-ranges', 'bytes'), ('server', 'Apache/2.2.12 (Ubuntu)'), ('last-modified', 'Tue, 23 Oct 2012 04:46:36 GMT'), ('etag', 'W/"567dd-105f-4ccb2a7a9a500"'), ('date', 'Tue, 23 Oct 2012 04:46:36 GMT'), ('content-type', 'application/pdf')]
multipart/form-data; boundary=----------lImIt_of_THE_fIle_eW_$
And I didn't try requests,Coz I would like to solve this with httplib(without any external lib)

To post parameters and a file in a body you could use multipart/form-data content type:
#!/usr/bin/env python
import requests # $ pip install requests
file = 'file content as a file object or string'
r = requests.post('http://example.com/SomeName/action.php',
files={'file': ('filename.txt', file)},
data={'str1': 'string1', 'str2': 'string2'})
print(r.text) # response
requests.post sends to the server something like-this:
POST /SomeName/action.php HTTP/1.1
Host: example.com
Content-Length: 449
Content-Type: multipart/form-data; boundary=f27f8ef67cac403aaaf433f83742bd64
Accept-Encoding: identity, deflate, compress, gzip
Accept: */*
--f27f8ef67cac403aaaf433f83742bd64
Content-Disposition: form-data; name="str2"
Content-Type: text/plain
string2
--f27f8ef67cac403aaaf433f83742bd64
Content-Disposition: form-data; name="str1"
Content-Type: text/plain
string1
--f27f8ef67cac403aaaf433f83742bd64
Content-Disposition: form-data; name="file"; filename="filename.txt"
Content-Type: text/plain
file content as a file object or string
--f27f8ef67cac403aaaf433f83742bd64--
To reproduce it with httplib see POST form-data with Python example.
A simpler solution if your parameters do not contain much data is to pass them in the url query part and leave the body to contain only the file:
#!/usr/bin/env python
import urllib
import requests # $ pip install requests
params = {'str1': 'string1', 'str2': 'string2', 'filename': 'filename.txt'}
file = 'file content as a file object or string, etc'
url = 'http://example.com/SomeName/action.php?' + urllib.urlencode(params)
r = requests.post(url, data=file, headers={'Content-Type': 'text/plain'})
print(r.text) # response
It corresponds to the following HTTP request:
POST /SomeName/action.php?str2=string2&str1=string1&filename=filename.txt HTTP/1.1
Host: example.com
Content-Length: 39
Content-Type: text/plain
Accept-Encoding: identity, deflate, compress, gzip
Accept: */*
file content as a file object or string
It should be easier to translate to httplib if you need it.

The following code can also solve the problem with transfering file with other meta data using httplib (with out any external libraries):
def document_management_service_success(self,str_loc_file_path,*args):
locfile = open(str_loc_file_path,'rb').read()
str_loc_file = locfile.split('#end_pymotw_header')
initial_data = str_loc_file[0]
encoded_data = ''.join("{0:08b}".format(ord(c)) for c in initial_data)
params = urllib.urlencode({'docName':'INVOICE', 'docNumber':'RF/2', 'cusName':'Tijo john', 'cusNumber':'C124', 'category':'INVOICE', 'data':encoded_data})
headers = {"Accept": "Text/*","Content-Disposition":"form-data" ,"Content-Type": "application/x-www-form-urlencoded, application/pdf, form-data"}
conn = httplib.HTTPConnection("efiling.nucoreindia.com")
conn.connect()
conn.set_debuglevel(1)
conn.request("POST", "/api/?task=create", params, headers)
response = conn.getresponse()
print "Server Response status is"+str(response.status)+"and Reason is,"+str(response.reason)
print response.getheaders()
print response.read()
pass

Related

Posting GZipStream to PHP failing to deflate

I am trying to post JSON using GZipStream to PHP but am not sure how to deflate it on the PHP side. Here is the function to compress:
public static string Compress( string text) {
var buffer = Encoding.UTF8.GetBytes(text);
var memoryStream = new MemoryStream();
using (var stream = new GZipStream(memoryStream, CompressionMode.Compress, true)) {
stream.Write(buffer, 0, buffer.Length);
}
memoryStream.Position = 0;
var compressed = new byte[memoryStream.Length];
memoryStream.Read(compressed, 0, compressed.Length);
var gZipBuffer = new byte[compressed.Length + 4];
Buffer.BlockCopy(compressed, 0, gZipBuffer, 4, compressed.Length);
Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gZipBuffer, 0, 4);
return Convert.ToBase64String(gZipBuffer);
}
It is being called like this:
request.Headers.Add("Content-Encoding", "gzip");
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
postData = Compress(JsonConvert.SerializeObject(incomingData));
byteArray = Encoding.UTF8.GetBytes(postData);
dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
On the PHP side I am doing this to receive it:
<?PHP
file_put_contents('test.txt', file_get_contents('php://input'));
file_put_contents('test2.txt', gzuncompress('php://input'));
?>
In my apache error log I get this:
PHP Warning: gzdecode(): data error in /var/www/html/gzip.php on line 3
and in test.txt I get this:
0QAAAB+LCAAAAAAABAAdjsEKgzAQRH9lycWLlfbquVLoRWntqelhiYsGZJNuorUU/70htzcPZhj102rAiFrVz4SNiJOWOxwpGa06F+I1OO7dnWQlgQM0myEfrePEvXxB6L1QiNWF4o2CdxxStdTqTBHtHPLMKZs8nvODafNkIg1gJhRMJEBs3MKJkv1MdibwKMHyCCvOC9XQVtBhnKAoSpgtExxL8C7YfOZYabW/dvUHutMCTtEAAAA=
I have also tried gzdecode, gzinflate, what should I do next to get my JSON back so I can process it with PHP?
UPDATE:
I tried doing what Sammitch suggested, but still getting errors. Using this (https://gist.github.com/magnetikonline/650e30e485c0f91f2f40) to dump all the request info provides the following:
POST /gzip.php HTTP/1.1
HTTP headers:
Authorization: Bearer xxxx
Host: mysite.com
Expect: 100-continue
Request body:
0QAAAB+LCAAAAAAABAAdjsEKgzAQRH9lyaUXK/bqWSn0UmntqelhiYsGZJNuorUU/70htzcPZhj102rAiFrVz4StiJMrdzhSMlp1LsRLcNy7O8lKAkdoN0M+WseJe/mC0HuhEMszxRsF7zikaqFVQxHtHPLMKZs8nvODafNkIg1gJhRMJEBs3MKJkv1MdibwKMHyCCvOC9XQlNBhnOBwKGC2TFAV4F2w+UxVarW/dvUHpEHFyNEAAAA=
I tried it both with and without the base64.

Send Raw Data from PHP Server API to Swift client API

My goal is to store and retrieve raw data from a PHP script and client Swift code using HTTP POST. I am using MySQL database storing MEDIUMBLOB data.
I successfully sent the data from Swift and stored it into database.
Here is my working code used to store the data (I removed the WHERE clause to simplify), I can see the stored raw data using PHPMyAdmin (e.g. [BLOB - 345.6 KiB] which is the same size as client code data size) :
<?php
//...
$file = $_FILES['file']['tmp_name'];
$file_data = file_get_contents($file);
$file_info = finfo_open(FILEINFO_MIME_TYPE);
$file_type = finfo_file($file_info, $file);
$file_size = filesize($file);
$worldMap1 = $file_data;
$query = $query = "INSERT INTO " . $this->table_name . " SET worldMap1=:worldMap1";
//...
?>
Client Swift code (request structure) :
let boundary = generateBoundaryString()
var request = URLRequest(url: requestedUrl)
request.httpMethod = POSTMETHOD
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpBody = createBodyWithParametersForData(
parameters: dataBody,
filePathKey: "file",
imageDataKey: data,
boundary: boundary
)
private func createBodyWithParametersForData(parameters: [String: Any]?, filePathKey: String?, imageDataKey: Data, boundary: String) -> Data {
var body = Data();
if parameters != nil {
for (key, value) in parameters! {
body.appendString(string: "--\(boundary)\r\n")
body.appendString(string: "Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString(string: "\(value)\r\n")
}
}
let filename = "file"
let mimetype = "application/octet-stream"
body.appendString(string: "--\(boundary)\r\n")
body.appendString(string: "Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.appendString(string: "Content-Type: \(mimetype)\r\n\r\n")
body.append(imageDataKey)
body.appendString(string: "\r\n")
body.appendString(string: "--\(boundary)--\r\n")
return body
}
Now I simply want to send the data back to client Swift code (non working code) :
<?php
// required headers
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
// Fetch the record:
$query = "SELECT worldMap1 FROM " . $this->table_name . "";
// prepare query
$stmt = $db->prepare($query);
//...
// execute query
$stmt->execute();
if ($stmt->rowCount() == 1) {
// Fetch the record into a variable:
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$file_size = filesize($row["worldMap1"]);
// Send the content information:
header("Content-Type: application/octet-stream\n");
header("Content-Disposition: attachment; filename=\"file\"\n");
header("Content-Length: {$file_size}\n");
// Send the file:
echo $row["worldMap1"];
}
// Omit the closing PHP tag to avoid tainting the downloaded file
On client side, I either receive 0 byte data or timeout error codes.
I also tried to hardcode the Content-Length value e.g. 1000.
I do not see any clear documentation on how to send raw data from PHP code.
Here is the only useful information I found and used to store the data : http://www.peachpit.com/articles/article.aspx?p=1967015&seqNum=4
Generally, files are stored in a directory and not in a database.
It looks like the problem is most likely with your Content-Type: application/octet-stream\n header. I don't think it's enough to just tell the browser hey, I'm expecting an octet-stream.
In order for your browser to recognize this as an attachment properly I would change the header to indicate the actual type of file you are dealing with so it knows how to interpret the file.
Like so:
header('Content-Type: ' . $type);
Here are a list of accepted MIME-TYPES
You are also over-writing your your content type header from the "required" application/json to the octet-stream. I would probably not send out the aplication/json header. Even though I believe it would be over-written by the latter.
Make sure you send your headers out before ANYTHING is outputted by the script. Even an unknown white space can cause you problems.
I also do not see the need for the \n in you header.
I would also consider using single quotes instead of double quotes as your likely to make mistakes escaping your double quotes for your file name.
Hope that helps.
Again, if it were me I would not do this. I would upload all the files to a directory not a db.

PHP MailSo library and attachments

I'm trying to use MailSo library to create MIME message. I have got to the point where next step is to process attachments. Everything is fine when attachments are binary files but when I try to to add plain text attachment as follow
$rResource = "Some plain text goes here";
$sFileName = 'text.txt';
$iFileSize = \strlen("Some plain text goes here");
$bIsInline = false;
$bIsLinked = false;
$sCID = $metadataCID;
$aCustomContentTypeParams = array(\MailSo\Base\Enumerations\Encoding::QUOTED_PRINTABLE_LOWER);
$oMessage->Attachments()->Add(
\MailSo\Mime\Attachment::NewInstance(
$rResource,
$sFileName,
$iFileSize,
$bIsInline,
$bIsLinked,
$sCID,
$aCustomContentTypeParams
)
);
I expect to see that attachment as
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename=text.txt
but it always forcing to base64 neither adding charset to content-type part as
Content-Type: text/plain; name="text.txt"
Content-Disposition: attachment; filename="text.txt"
Content-Transfer-Encoding: base64
Any tips on that?
It looks like MailSo library treats all attachments except message/rfc822 as binaries. It will require to rewrite or extend createNewMessageAttachmentBody() private function.

Prestahop Order Webservice Issue

Trying to put an order via webservice. I've followed the correct order via webservice:
Create customer (customers blank schema)
Create customer's address (addresses blank schema)
Create associated customer's cart(carts blank schema)
Create Order (orders blank schema)
The problem is when order will be created and saved in database. I've launched the function which imports data into client + address + cart + order; aparently everything works fine, client, address and cart was created correctly, but not the order...
I've tested on php 5.6.30 server on my localhost lap and everything works fine but in a production php 5.5.9 server orders won't be created...
This is the function to create order:
$xml = $webService->get(array('url' => PS_SHOP_PATH .'api/orders/?schema=blank'));
$pedido = $xml->children()->children();
$direccion = getDireccion($idCliente, $webService);
$carrito = getCarrito($idCarrito, $webService);
$numProdPedido = count($carrito->associations->cart_rows->cart_row);
$pedido->id_address_delivery = $direccion['address']['id']; // Customer address
$pedido->id_address_invoice = $direccion['address']['id'];
$pedido->id_cart = $idCarrito;
$pedido->id_currency = $carrito->id_currency;
$pedido->id_lang = $carrito->id_lang;
$pedido->mp_order_id = $refPedido;
$pedido->reference = $refPedido;
$pedido->id_customer = $carrito->id_customer;
$pedido->id_carrier = $carrito->id_carrier;
$pedido->payment = $refPedido;//$pedido_ws['paymentType'];
$pedido->module = 'cashondelivery';
$pedido->total_paid = $pedido_ws['total_price'];
$pedido->total_paid_real = $pedido_ws['total_price'];
$pedido->total_products = $numProdPedido;
$pedido->total_products_wt = $numProdPedido;
$pedido->conversion_rate = 1;
// Others
$pedido->valid = '1';
$pedido->current_state = '1';
getEstadoPedido($pedido->order_state);
$pedido->total_discounts = $pedido_ws['promotions']['total_deduced_amount'];
$pedido->total_discounts_tax_incl = $pedido_ws['promotions']['total_deduced_amount'];
$pedido->total_discounts_tax_excl = $pedido_ws['promotions']['total_deduced_amount'];
$pedido->total_paid_tax_incl = $pedido_ws['total_price'];
$pedido->total_paid_tax_excl = $pedido_ws['total_price'];
$pedido->total_shipping = $pedido_ws['shipping_price'];
$pedido->total_shipping_tax_incl = $pedido_ws['shipping_price'];
$pedido->total_shipping_tax_excl = $pedido_ws['shipping_price'];
$ind = 0;
foreach($carrito->associations->cart_rows->cart_row as $producto){
$prod = getProductoById($producto->id_product, $webService);
$pedido->associations->order_rows->order_row[$ind]->product_id = $producto->id_product;
$pedido->associations->order_rows->order_row[$ind]->product_attribute_id = $producto->id_product_attribute;
$pedido->associations->order_rows->order_row[$ind]->product_quantity = $producto->quantity;
$pedido->associations->order_rows->order_row[$ind]->product_name = $prod->name->language[0];
$pedido->associations->order_rows->order_row[$ind]->product_reference = $prod->reference;
$pedido->associations->order_rows->order_row[$ind]->product_price = $prod->price;
$pedido->associations->order_rows->order_row[$ind]->unit_price_tax_incl = $prod->price;
$pedido->associations->order_rows->order_row[$ind]->unit_price_tax_excl = $prod->price;
$ind++;
}
// Creating the order
$opt = ['resource' => 'orders'];
$opt['postXml'] = $xml->asXML();
$xml = $webService->add($opt);
Any clues?
Edit: XML request and response code when calling order webservice. This is the last order xml.
HTTP REQUEST HEADER
POST //api/orders HTTP/1.1
Authorization: Basic WDMxSlRJRjFTNTNIMVlTS0hZRUFHTjlJVk5CQ1ZHTlg6
Host: www.mywebsite.com
Accept: */*
Content-Length: 1956
Content-Type: application/x-www-form-urlencoded
HTTP RESPONSE HEADER
HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Wed, 26 Apr 2017 10:08:06 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Authorization,Accept-Encoding
X-Powered-By: PHP/5.5.9-1ubuntu4.19
Set-Cookie: PrestaShop-300d307acc0ec8525a71119b0dd393d8=0XUqFuC%2BvHy%2B%2BAU8Uod5odM7En0QQlQNh2ZWuI7VO6wTSlgh%2F%2FlVEDyz4e%2BJUv55b3N6fHTdEz%2Fmyjob65wxqjofdRVglsNIauli6yfcEBQ%3D000079; expires=Tue, 16-May-2017 10:08:05 GMT; Max-Age=1727999; path=/; domain=www.mywebsite.com; httponly
XML SENT
<?xml version="1.0" encoding="UTF-8"?>
<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
<order>
<id/>
<id_address_delivery>31754</id_address_delivery>
<id_address_invoice>31754</id_address_invoice>
<id_cart>1314430</id_cart>
<id_currency>1</id_currency>
<id_lang>1</id_lang>
<id_customer>22578</id_customer>
<id_carrier>1</id_carrier>
<current_state>3</current_state>
<module>cashondelivery</module>
<invoice_number/>
<invoice_date/>
<delivery_number/>
<delivery_date/>
<valid>1</valid>
<date_add/>
<date_upd/>
<shipping_number/>
<id_shop_group/>
<id_shop/>
<secure_key/>
<payment>40862744-A</payment>
<recyclable/>
<gift/>
<gift_message/>
<mobile_theme/>
<total_discounts>0</total_discounts>
<total_discounts_tax_incl>0</total_discounts_tax_incl>
<total_discounts_tax_excl>0</total_discounts_tax_excl>
<total_paid>25.98</total_paid>
<total_paid_tax_incl>25.98</total_paid_tax_incl>
<total_paid_tax_excl>25.98</total_paid_tax_excl>
<total_paid_real>25.98</total_paid_real>
<total_products>1</total_products>
<total_products_wt>1</total_products_wt>
<total_shipping>2.99</total_shipping>
<total_shipping_tax_incl>2.99</total_shipping_tax_incl>
<total_shipping_tax_excl>2.99</total_shipping_tax_excl>
<carrier_tax_rate/>
<total_wrapping/>
<total_wrapping_tax_incl/>
<total_wrapping_tax_excl/>
<round_mode/>
<conversion_rate>1</conversion_rate>
<reference/>
<associations>
<order_rows>
<order_row>
<id/>
<product_id>233154</product_id>
<product_attribute_id>0</product_attribute_id>
<product_quantity>1</product_quantity>
<product_name>Smartwatch Gt08 Sim sd bluetooth Negro plata</product_name>
<product_reference>8435338885678</product_reference>
<product_ean13/>
<product_upc/>
<product_price>25.920000</product_price>
<unit_price_tax_incl>25.920000</unit_price_tax_incl>
<unit_price_tax_excl>25.920000</unit_price_tax_excl>
</order_row>
</order_rows>
</associations>
</order>
</prestashop>
RETURN HTTP BODY
**Here is blank space, don't know if there will be some response xml code...
Try setting these to an empty string. If that doesn't work try setting it to your product ID.
$xml->order->associations->order_rows->order_row[$i]->product_attribute_id
and
$xml->cart->associations->cart_rows->cart_row[$i]->id_product_attribute

Post image from linux (using c without curl) to php server

I am using v4l2 library on linux, take a picture and want to send it to a php server via c program.
I want to using a socket to do it. But i don't know how to pass the image to request .
This is my sample code:
int portno = 80;
struct sockaddr_in serv_addr;
int sockfd, bytes, sent, received, total;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
char message[1024],response[4096];
if (sockfd < 0){
printf("ERROR opening socket");
}
memset(&serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portno);
if(inet_pton(AF_INET, CONST_DOMAIN, &serv_addr.sin_addr)<=0){
printf("\n inet_pton error occured\n");
return 1;
}
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) {
printf("ERROR connecting");
}
char content[1024];
char *contentTemp="image_name=%s";
sprintf(content,contentTemp,imageName);
char *headerTemp="POST %supload.php HTTP/1.0\r\nHost: %s\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-length: %d\r\n\r\n%s";
sprintf(message,headerTemp,SERVICE_PATH,SERVICE_HOST,strlen(content),content);
write(sockfd,message,strlen(message));
Can i using this way to post an image to server (include its name) ?
Any suggest for me ?
Thanks
PS: sorry about my english skill.
You are including only file name. You have to include the whole image file contents into post data stream. Forms submitting binary data with POST request should use multipart/form-data content type. You can't use application/x-www-form-urlencoded type.
From HTML 4.01 specification:
The content type "application/x-www-form-urlencoded" is inefficient
for sending large quantities of binary data or text containing
non-ASCII characters. The content type "multipart/form-data" should be
used for submitting forms that contain files, non-ASCII data, and
binary data.
You could adjust your code like this:
char *filename="file.jpg"; // this example uses jpeg
// optionally load file from filesystem
// though I think you have it in a buffer, don't you?
FILE *file = fopen(filename, "rb");
char binary[1024]; // adjust buffer size to your needs
size_t filesize = fread(binary, 1, sizeof(binary), file);
// check for error here to make sure read succeeded
fclose(file);
// multipart/form-data POST header
const char *headerTemp = "POST %supload.php HTTP/1.0\r\n"
"Host: %s\r\n"
"Content-Type: multipart/form-data; boundary=BoUnDaRy\r\n"
"Content-Length: %lu\r\n"
"\r\n";
// first and only part beginning
const char *bodyTemp =
"--BoUnDaRy\r\n"
"Content-Disposition: form-data; name=\"file\"; filename=\"%s\"\r\n"
"Content-Type: image/jpeg\r\n"
"Content-Transfer-Encoding: binary\r\n"
"\r\n";
// and ending
const char body2[] = "\r\n"
"--BoUnDaRy--\r\n";
char body1[1024]; // adjust buffer size to your needs
// calculate body size, will be included in Content-Length header
size_t body_size = strlen(body1) + strlen(body2) + filesize;
snprintf(header, 1024, headerTemp, SERVICE_PATH, SERVICE_HOST, body_size);
snprintf(body1, 1024, bodyTemp, filename);
// you should add checking for each write return value
write(sockfd, header, strlen(header));
write(sockfd, body1, strlen(body1));
write(sockfd, binary, filesize);
write(sockfd, body2, strlen(body2));
After sending data you should read server response, for example:
while (1) {
ssize_t result = recv(sockfd, response, sizeof(response), 0);
if (result == 0) {
break;
} else if (result < 0) {
perror("reading socket failed");
break;
}
printf("%s\n", response);
}
close(sockfd);
If you just close socket without waiting for the response server may complain and return error. You should also check if the response confirms valid request.

Categories