简体   繁体   中英

PHP File Upload, using the FILES superglobal array

Let's say that I'm setting up an upload feature for a project. I'm using PHP5, and I was wondering if by using the $_FILES superglobal array, I could have access to the "tmp_name" array key , which is the temporary path and name of the file being uploaded to display a preview of the image, before moving it to the "uploads" folder in the server.

What I had in mind is something like this: Use jQuery to detect when the "file" input filed changes (when the user selects an image file), then place an ajax call to upload the the file, which will move it to the temp folder even before I use "move_uploaded_file". If I can somehow access the "tmp_name" array key, I could probably put it into and "img" tag to display a preview. Later move the file to it's final location when the submit button is clicked.

I'm not asking for any code examples or anything, since I'd be thrilled to accomplish this on my own, I just want to find out if there is access to that array key in any way.

Yes, you can.

In PHP, when a user submits a form with a the $_FILES superglobal is populated with useful information about the uploaded file. Inside you'll find each uploaded file's original name, content-type, temporary upload location on the server, an error code, and the size in bytes.

Taken from Fixing the $_FILES superglobal

Here is the example print_r output taken from the website of the $_FILES array,

Array
 (
    [download_zip] => Array
     (
        [name] => dummy.txt
        [type] => text/plain
        [tmp_name] => /Applications/MAMP/tmp/php/php5TBPsw
        [error] => 0
        [size] => 1
     )

    [download_screenshot] => Array
     (
        [name] => dummy.txt
        [type] => text/plain
        [tmp_name] => /Applications/MAMP/tmp/php/phpTncd39
        [error] => 0
        [size] => 1
     ) 
)

You can access the tmp_name by using $files_array['download_zip']['tmp_name'] syntax.

Update:

$path = $files_array['download_zip']['tmp_name'];
echo "<img src='$path'>"; 

To use these in an image tag, you will need to store the relevant temp files somewhere inside the web root, since they are often somewhere else in the file system, outside the web root, and you don't want to output that path to the user, as it will both be useless (an img tag can't map to that path), and bad security (your are giving away information about your file system).

You can do this by a) copying each file to a spot in the webroot (costly), or b) changing your config to put all uploaded files into a temp folder inside the web root (big security implications).

Keep security in mind while you are planning this out...

Just be careful about the security of other temp files. Be sure only the ones relevant to this part of this application are stored inside the web root. You don't want to find that you've given enough information to allow somebody to calculate access to other files and have some sort of cross-user data breach because other uploaded data is available (even for a very short time) in your web root.

This may be a better way:

Perhaps a better solution would be to grab the temp name, obfuscate it somehow, add it to a path that will pass it to a gatekeeper file, and send that instead.

Something like

/images/path/to/gatekeeper.png?name=[obfuscated file name here]

You can then use /images/path/to/.htaccess to make sure the gatekeeper is treated as a php file rather than a png file, by adding:

<Files gatekeeper.png>
    ForceType application/x-httpd-php
</Files>

Now, the gatekeeper can un-obfuscate the file name, pull it from the temp path, and send it, without revealing anything to the user, moving the actual file, or changing your config.

Just make sure you don't expect the file to persist, because if they refresh later, and the file has moved (almost certainly will have), it will just be a broken image. Maybe check existence with the gatekeeper and give them a "File No Longer Available" image if it's not found. You can also enforce sending of image files only, or other security issues at the gatekeeper level.

You can do the gatekeeper as so (typed from memory, probably won't run, and has no handling of errors, missing values, etc, but you should be able to use this as a starting point...):

<?php
// This is all inside gatekeeper.png, which is just a .php file with a .png extension
// It's not very good code, just an example to point you in the right direction.

// Specify this will be a png file for the browser...
header("content-type: image/png");


//Read the file name from the $_GET and un-obfuscate it.
$file = "/path/to/temp/directory/outside/file/root/that/we/hopefully/have/access/to/";
$file .= $_GET["name"];


// Check that the file exists, and send a "not found" image if not.
// http://us.php.net/manual/en/function.file-exists.php
if (!file_exists($file)) {etc...}


// Read the image file, send it to the user, and close it...
// http://us.php.net/manual/en/function.imagepng.php
$im = imagecreatefrompng($file);
imagepng($im);
imagedestroy($im);


die();

?>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM