httppostfrompys60tophp

Uploading from PyS60 to PHP

HTTP Post never felt so good

more tutorial pages

Jürgen's awesome tutorial gets you going. But sometimes, you need to do something a little more complicated with an upload. I focus here on the HTTP Post.

Upload text to a file

Example 17 of the Mobilenin tutorial starts with a simple HTTP post of some text form data. Let's recap. First, here are the files if you want to download them: python php

If you have some data (in a variable called test1), you must first URL Encode the data to remove bad characters like spaces and such.

params = urllib.urlencode({'data': test1})

The params can have mutliple parts, like for form data you might have:

params = urllib.urlencode({'data': test1,

'name' : my_name,

'age' : 32})

All the data will get posted with the given names. So now you setup the HTTP headers, so the PHP knows we are giving it URL Encoded data.

headers = {"Content-type": "application/x-www-form-urlencoded",

"Accept": "text/plain"}

Here we make an HTTPConnection object pointing to our website.

conn = httplib.HTTPConnection("www.leninsgodson.com")

Now we send the POST request.

conn.request("POST", "/courses/pys60/php/set_text.php", params, headers)

With the data uploaded, we now get the res.

response = conn.getresponse()

Then remember to close the connection.

conn.close()

On the Server side, our task is simple.

<?php

$filename = 'textfile.txt';

// Open a file for appending

$handle = fopen($filename, 'a+');

// Get the data from the POST request

$data = $_POST['data'];

// PHP recommends writing the exact data length

fwrite($handle, $data, strlen($data));

// Append a newline

fwrite($handle, "\n");

// close the file

fclose($handle);

// Send data back to the phone

echo 'data received OK';

?>

Upload Binary to a File

Now with binary files, it becomes a little more tricky. In general you should avoid sending binary data that is URL encoded. Why? Among other reasons, its painfully slow just to do the encoding on your PyS60 device and increases the download size.

First, heres the files: python php

In this example, I am using a wav file...you could have video or whatever. First, lets say we read in some binary chunk:

# Read the wav file from disk

f = open(filename,"rb")

chunk = f.read()

f.close()

Then, I like to gzip the data. Pretty quick on the phone and saves upload time.

chunk = chunk.encode("zlib")

Like before, we set up headers, declaring the upload type is gzip. Change your MIME type to fit your needs.

headers = {"Content-type": "application/x-gzip",

"Accept": "text/plain"}

Then we send the request, as before, pushing the gz data as the params in the previous example.

conn = httplib.HTTPConnection(host)

conn.request("POST", path, chunk, headers)

Finally, get the response, and close the request:

response = conn.getresponse()

remote_file = response.read()

conn.close()

On the server side, things simplify a bit because we only have one data to pull from the POST. php://input does the work for us.

<?php

// Read the raw http data from the post

$data = file_get_contents('php://input');

// Ungzip the wav file

$chunk = gzuncompress($data);

if (!$chunk) {

echo -1;

die();

}

// Write the wav to disk with a unique filename

$uid = uniqid();

$filename = "$uid.wav";

$filepathname = "wavfiles/$filename";

$handle = fopen($filepathname, 'wb');

fputs($handle, $chunk, strlen($chunk));

fclose($handle);

?>

Multipart Form Data

So here is a problem. What if you want to upload some binary data and some text. As I said earlier you can push this into an URL-ENCODED message. But that is painfully slow as we have to first MIME/Base-64 encode our data, then url-encode it. On the server, this isn't so bad. On a phone, a 100k file can take a few minutes. Lucky for us, we can make a post ourself which consists of some text data and some files that we want to upload. If your binary data is in memory, thats ok too.

Additional tip from simo: it is good to use multipart/form-data because (usually) server allows to upload bigger files with that method.

Now, the issue is, Python has no built in support for this kind of post. Fortunatly, activestate.com had some sample code for doing this in Python. With a few modifications, it can be made to work on PyS60.

Note: If you are using an N80, this code will only work on newer firmware (>= 2007SE_3.2007.10-7). Check your firmware version by dialing *#0000#. You can flash upgrade your device using Nokia's updater.

Download the code: Python PHP

The way we will use this is:

    • Read the files,

    • Make two lists, one for our text and one for our binary files.

    • Then we post the data.

filename = u'd:\\440.wav'

f = open(filename)

value = f.read()

f.close

fields = [('description', 'concert pitch')]

files = [('data', filename, value)]

print post_multipart('www.yourcomputer.domain',

'/path/to/some.php',

fields,

files)

I'll leave you to review the Python code to see how this works in detail. For our PHP, we have to handle the FILE upload and the form POST data.

<?php

$dir = realpath('.');

$filepathname = "$dir/wavfile.wav";

// Verify the file was an uploaded one, to thwart attacks.

if (is_uploaded_file($_FILES['data']['tmp_name'])) {

echo "File ". $_FILES['data']['tmp_name'] ." uploaded successfully.\n";

// you MUST move the file from the temp space to your new location,

// if you don't the file will be deleted when the script ends.

if(move_uploaded_file($_FILES['data']['tmp_name'], $filepathname)) {

echo "Alls well!";

}

} else {

echo "Possible file upload attack: ";

echo "filename '". $_FILES['data']['tmp_name'] . "'.";

}

// All of the field data can be accessed via the POST array.

$f = $_POST['description'];

echo $f;

?>

So that's about it! Text, file, text & file or muti-file uploads via HTTP POST for PyS60! Enjoy!

© Copyright David Ayman Shamma: ayman shamma•gmail com