Monday, March 17, 2014

Uploading files to a webpage via html/php

Here's the situation. You have a bash script you wrote to analyze a file and save that analysis to some output file. But instead of running this on the command line, you want to have a webpage where someone can go to and upload the file for automatic analysis. Sounds simple, but it took me a little trial and error to get it working right.

To Do List
  1. Have a "Browse" button where someone can search their computer for a file to upload. 
  2. Have a "Submit" button after finding the file to upload.
  3. Have an error if no file is selected (main point is don't run script with an empty file).
  4. Have unique filename used per upload. Why? Because you cannot use static anything since two people may upload files at the same time.
  5. Have webpage redirect to script output once completed (unique url).


 So here's the part for the html for the browse/submit part. You put this in the html page you actually want the buttons to appear in. Essentially this will put a browse and submit button on the page and on clicking submit, it will call up the "upload_file.php" script.

<form action="upload_file.php" method="post"
enctype="multipart/form-data">
<label for="file">File to upload</label>
<input type="file" name="file" id="file"><br><br>
<input type="submit" name="submit" value="Submit">
</form>


After submit is clicked, I needed a bash script to be called and the file passed on to the script. Admittedly this part could probably be better but I sort of messed around with it until I got it working. If no file is selected, it just prints an error and does not run the script. If a file is chosen, it runs the else statement where it calls a script (in the same directory as the page) with the file name as an input variable to the script ($1).

<?php
if ($_FILES["file"]["error"] > 0) 
 {
  echo "Error: " . $_FILES["file"]["error"] . "<br>";
  }
else
  {
  $file = $_FILES["file"]["tmp_name"];
  exec ( "./script.sh $file" );
  $url = 'http://website.corp/OutPutDirectory';

  echo '<META HTTP-EQUIV=Refresh CONTENT="0; URL='.$url.$file.'">';  
    }
?>


By default, any uploaded file is uploaded in to the /tmp directory as something like /tmp/phpgthJhd. In the script above, I set that tmp name to $file so when the script is called it knows what file to run the script against. This random naming has the benefit of php already taking care of unique name too. Each upload will have a different name. Another benefit is that after the php script completes, the /tmp file is deleted. Auto-clean up.

One thing to note in the above are these two lines:

  $url = 'http://website.corp/OutPutDirectory';  
  echo '<META HTTP-EQUIV=Refresh CONTENT="0; URL='.$url.$file.'">'; 

The $url is set to the obvious link, however notice below I added $file. And $file is /tmp/php<random>. Here was my fix for utilizing this built in file path to the unique url. In my output directory, I just added a /tmp directory too. So I can simply have my script output the file to that directory since php is already going to forward to that.

The php redirect to the output will look like this:

http://website.corp/OutPutDirectory/tmp/phpgthJhd

In the script you do something similar:

file=$1
output to /var/www/OutPutDirectory$file.html

In both cases, the / in the file is referencing root but since I'm putting directories in front, it's just another separator.


So you now have a place in a webpage to upload a file, error if no file uploaded, random and unique file names, and the php/bash script are talking with the same random filename. So yeah everything works as needed for now. If you have any issues, a good place to check is the apache error log.