ColdFusion versus PHP – Uploading a File

I spent part of my vacation digging into PHP. I’d like to be much savvier with PHP because we’ve seen a big chunk of Flex adoption from the PHP community and I’d like to be able to talk to those developers more intelligently. Unfortunately my server-side programming chops are very, very rusty. I started out as a ColdFusion developer and I’ve been able to play with some of the new stuff in ColdFusion 9 but I haven’t built a real CF app in a long time. So I thought I’d do a bit of a comparison and I’ve started doing simple things in PHP and then replicating them in ColdFusion. The first one is file uploading.

Disclaimer: I’m assuming there are things I’m doing wrong. File uploading is fairly basic, but part of the reason I want to blog the basic stuff is so people can let me know where I’m messing up and what I could do better. So flame on in the comments.

The Code Comparison

PHP – file_upload.php

<body>
<?php
     ini_set('display_errors',1);
     error_reporting(E_ALL | E_STRICT);
 
     if(isset($_POST['submitted']))
     {
          if( move_uploaded_file($_FILES['myfile']['tmp_name'], "{$_FILES['myfile']['name']}") )
          {
               print '<p>It verked!</p>';    
          } else {
               print '<p>Problemo!</p>';
          }         
          print_r($_FILES);
     }
?>
     <form action="upload_file.php" enctype="multipart/form-data" method="POST">
          <input type="hidden" name="MAX_FILE_SIZE" value="3000000" />
        <p><input type="file" name="myfile" /></p>
        <p><input type="submit" name="submit" value="Upload" /></p>
        <input type="hidden" name="submitted" value="true" />
    </form>
</body>

ColdFusion – file_upload.cfm

<cfifisDefined("form.submitted">
     <cfset currentPath = getCurrentTemplatePath()>
     <cfset currentDirectory = getDirectoryFromPath(currentPath)>
     <cffile action="upload" nameconflict="overwrite" filefield="form.myfile" destination="#currentDirectory#/coldfusion.gpx"/>
     <cfif cffile.filewassaved eq true>
          <p>It verked!</p>
          <cfdump var="#cffile#"/>
     <cfelse>
          <p>Problemo!</p>
     </cfif>
</cfif>
<body>
     <formaction="upload_file.cfm" enctype="multipart/form-data" method="POST">
        <p><inputtype="file" name="myfile" /></p>
        <p><inputtype="submit" name="submit" value="Upload" /></p>
        <inputtype="hidden" name="submitted" value="true" />
    </form>
</body>

Thoughts

I thought it was interesting how PHP and ColdFusion differ in the actual upload mechanism. Both of them just upload the file to a temporary location but then how the programmer deals with it is different. With PHP, you “move” the file to a location of your choice with the move_uploaded_file method. With ColdFusion you use cffile but call the upload attribute instead of the move attribute. That's why you don't put # signs around the form.myfile attribute because the upload function in cffile uses the POST info and that filefield attribute to do the moving/copying behind the scenes. Not sure which one I like better.

A few other bits. One, ColdFusion seems to give way, way more information about the file you've uploaded. I don't know if there is a way to get that kind of detail from PHP, but with ColdFusion I get a bunch of attributes like filewassaved, fileexisted, filewasappended, serverfileext, serverfilename etc. Some of that I can parse from the PHP information, like the file name and file extension, but other information, like if it was overwritten, or if the file already existed, doesn't seem possible to get with PHP. Two, it is really, really annoying to use a relative file path with ColdFusion. The move_uploaded_file function uses a relative path so it's easy to upload it to the same directory. With ColdFusion it's a pain, which is why I had to set a couple of extra variables. Also, PHP seems to love to check that you're below the max file size. You have to set one in your php.ini file and then send it again as a hidden form field. That seems completely redundant and I can't figure out why they do that.

Like I said above, this is supposed to be a pretty basic example because I want to know if I'm doing something stupid. If so, or if you have any additional info on my thoughts above, let me know.

  • Wez

    Hey Ryan, nice work man. I hope you do a few more of these! I’ve not really used CF myself so this is a nice comparison.

    Cheers!

    Wez

  • Wez

    Oh and I think the PHP.ini stuff is just some basic security. You know, in case some hacker decides to bypase your HTML MAX_FILE_SIZE restriction ;)

  • http://andymatthews.net/ andy matthews

    Try this again…

    Ryan. In your ColdFusion code, you could replace these two lines:
    <cfset currentPath = getCurrentTemplatePath()>
    <cfset currentDirectory = getDirectoryFromPath(currentPath)>

    with this line:
    <cfset currentDirectory = ExpandPath(‘./’)>

  • ryanstewart

    @Wez, thanks dude! I’d think the ini file would be more secure than having a hidden input, but maybe both of them provide that extra layer.

    @Andy, ahhh, duh, I completely forgot about that. And then I could just use that inside of my CFFILE tag and completely remove those two lines.

    I still think it’s a bit odd that cffile isn’t relative path right off the bat, but I want to find out why that is.

    =Ryan
    ryan@adobe.com

  • http://podkowski.com Karol Podkowski

    In PHP I think you should first check is the file even uploaded with is_uploaded_file or turn error printing in move_uploaded_file (when the file doesn’t exists it print error) with @ so: @move_uploaded_file
    Also stupid to mention but with bigger things important, when don’t have to don’t insert variables between “” :)

    For the file size try http://php.net/manual/en/function.ini-set.php :) Very tested but it may help do it a bit faster :)

  • http://www.dgrigg.com Derrick Grigg

    Here’s an example of php and coldfusion file uploading from Flash and Flex
    http://www.dgrigg.com/post.cfm/08/02/2007/Flex-and-Flash-file-uploading-with-return-data

  • http://www.automatem.co.nz Jochen Daum

    Ryan, I think the additional attributes in PHP are not present, because you are not forced to move the file into your server file space. You may for example straight away email it off or load it into a database field.

  • Darren

    The MAX_FILE_SIZE is just a convenience. You can safely leave it out and you’ll still receive an error if the file size is too big. However, if you put it in, PHP will catch that the file is too big before the upload begins rather than after. Which behaviour does CF have, ie. does it tell you before or during/after the upload that you’re filesize is too big?

  • Dave

    Either way you should never ever ever be just uploading to a folder in the webroot anyways and to make a “good” uploader is going to take some additional code.

    I don’t know about php but coldfusion uploads into a temp directory (which I would assume is a bit safer) and with Railo or cf9 you can load the upload right into a virtual file system to check the heck out of it before sending it on it’s way so that it can’t cause harm or let the user interact with it until it’s been checked.

    The problem is that everyone sees all these easy examples of uploading and they don’t learn or realize that they better being a lot more than these brief examples.

  • Marylka

    How do I upload it on my server with ColdFusion. The combination of ColdFusion and Flex 4.

    THX