problem with network.request() using POST

@develephant, We were going to do a tutorial on uploading files, but we ran into some technical problems and back burnered it. If I remember correctly, network.upload() does an HTTP PUT request and the $_FILES[] array should hold the uploaded info.  Some of the problems I ran into had to do with not being able to get the filename there.  I had to make up my own header entry for the file name and coax the PHP script to read it. 

The way most PHP scripts work wants to use the mime multi-part method.  You would use network.request() for this and I used the multipart class out of the old community code library. 

But what may be the problem is a setup issue on the PHP side.  If you google “empty $_POST”, there will be several posts that offer suggestions that might get you moving in the right direction.

@anthony113, you need to look up PHP Multipart Form uploads and see if that gets you started.

Rob

@Rob Miracle Thanks.  I will look into the PUT option.

I’m curious then what the use case is for network.upload() when it does not seem to jive with one of the major web scripting engines simply.

Thanks again.

I thought you said you could use it to upload to parse?  You can use PHP but you have to open the stream to get the data.  The code on the server side looks something like:

    /\* PUT data comes in on the stdin stream \*/     $putdata = fopen("php://input", "r");     if ($putdata) {         /\* Open a file for writing \*/         $tmpfname = tempnam("upload", "myapp");         $fp = fopen($tmpfname, "w");         if ($fp) {             /\* Read the data 1 KB at a time and write to the file \*/             while ($data = fread($putdata, 1024)) {                 fwrite($fp, $data);             }             /\* Close the streams \*/             fclose($fp);             fclose($putdata);             rename($tmpfname, "upload/" . $filename);                         Header("HTTP/1.1 201 Created");             echo("File Created");         } else {             Header("HTTP/1.1 403 Could not open tmp file." . $tmpfname);             echo("Could not open tmp file " . $tmpfname);         }     }

That should work with network.upload().  But if you notice I have a variable $filename.  That name is not natively passed to the server with this method. I had to make up my own file name system.

Now I haven’t used that code in a long time, so there are no warranties expressed or implied.  Your mileage may vary.  It’s completely unsupported.

@Rob Miracle First, thank you for sharing that code.  It creates the file, but the size is 0, so it’s got to be a config issue on my side.  I’ve probably read hundreds of pages on the issue, but still no luck.  I’m not running fcgi, it’s just straight apache mod.  pnp.ini is letting all the post vars though, etc.

And yes, network.upload() works flawlessly for Parse.  It would just be nice to know how that could work for us PHP users. :slight_smile:

I’m going to try a few other builds to see if I can get some action.  Thanks again, I appreciate you taking the time to reply.

Cheers.

@develephant - Thanks for trying to find a solution that will work. It will take the impossible out of the equation for us non-PHP wizards.

I just spent a little bit verifying this works – at least on my personal web host.  I’ve pinged engineering to get their blessing on the complete script and if they are okay with it, I’ll post the full script that does some filename checking, making sure the file isn’t too large, returns a full complement of errors etc.  Sounds like it could be a good Tuesday tutorial, though I have like 3-4 weeks of those queue up in front of it.

It’s possible I didn’t paste in everything needed, but I would suspect it might be a hosting issue.  I didn’t have to do anything (my personal test site is hosted with Hostgator). 

I am definitely looking forward to this tutorial. I tried this sample code (https://developer.coronalabs.com/code/upload-binary-corona-php-script) and it works when I try uploading a image (jpg).

To add on, that code does not provide a way to send in the filename together with it. So, you will need to modify it, so that the filename is sent together with the HTTP header, so the PHP-server side knows what filename it should be.

PHP-server side :

\<?php // Used when this function in PHP does not exist function apache\_request\_headers() { $arh = array(); $rx\_http = '/\AHTTP\_/'; foreach($\_SERVER as $key =\> $val) { if( preg\_match($rx\_http, $key) ) { $arh\_key = preg\_replace($rx\_http, '', $key); $rx\_matches = array(); // do some nasty string manipulations to restore the original letter case // this should work in most cases $rx\_matches = explode('\_', $arh\_key); if( count($rx\_matches) \> 0 and strlen($arh\_key) \> 2 ) { foreach($rx\_matches as $ak\_key =\> $ak\_val) $rx\_matches[$ak\_key] = ucfirst($ak\_val); $arh\_key = implode('-', $rx\_matches); } $arh[$arh\_key] = $val; } } return( $arh ); } // Get filename from headers $headers = apache\_request\_headers(); $filenameInHeader = 'FILENAME'; $filename = $headers[$filenameInHeader] ; $pngdata = $HTTP\_RAW\_POST\_DATA; if( isset( $pngdata ) ) { $img\_file = fopen ($filename, 'wb'); fwrite ($img\_file, base64\_decode( $pngdata )); fclose ($img\_file); echo "Success."; } else { echo "Failure."; } ?\>

Corona side :

local filenameToPhp = "yourfilenamehere.jpg" local function uploadBinary ( filename, url, onComplete ) local mime = require "mime" local path = system.pathForFile( filename ) local fileHandle = io.open( path, "rb" ) if fileHandle then local params = { headers = { ["Content-Type"] = "multipart/text", ["Filename"] = filenameToPhp, }, body = mime.b64( fileHandle:read( "\*a" ) ), progress = "upload", } io.close( fileHandle ) local function networkListener ( event ) print("main networkListener phase : " , event.phase, event.isError , event.response ) if event.phase == "began" then print( "main event.bytesEstimated : " , event.bytesEstimated ) elseif event.phase == "progress" then print( "main event.bytesEstimated, event.bytesTransferred : " , event.bytesEstimated, event.bytesTransferred ) elseif event.phase == "ended" then if (onComplete) then onComplete(event); end end return true; end network.request( url, "POST", networkListener, params) end end uploadBinary ( "localFilenameToUpload.jpg", "http://www.yoursite.com/uploadFile.php" , nil )