Fake uploading files
A few days ago I encountered a problem where I needed to test a controller that handles file uploads. I couldn’t find an easy way to unit test the code which used built-in uploading functionality so I decided to whip up this simple extension that allows to fake file uploads.
The extension is doing things that shouldn’t be done, it probably doesn’t even run anywhere else than on CLI, it is insecure, it might behave incorrectly but in this scenario it worked fine so I decided to share it. Don’t ask for support or any updates for this extension and use it on your own risk. I take no responsibility of anything (especially related to this extension).
The following example code might work with the extension:
- <?php
- fakeupload_file("userFile", '/Users/test/test.txt',
- "/tmp/upload.tmp", "text/plain", "This is a test upload");
- var_dump(is_uploaded_file('/tmp/upload.tmp'));
- var_dump($_FILES);
- var_dump(move_uploaded_file("/tmp/upload.tmp", "/tmp/test_file.txt"));
- unlink("/tmp/test_file.txt");
- ?>
And it can be executed using:
- # php -dfakeupload.enabled=1 test.php
- bool(true)
- array(1) {
- ["userFile"]=>
- array(5) {
- ["name"]=>
- string(20) "/Users/test/test.txt"
- ["type"]=>
- string(10) "text/plain"
- ["tmp_name"]=>
- string(15) "/tmp/upload.tmp"
- ["error"]=>
- int(0)
- ["size"]=>
- int(21)
- }
- }
- bool(true)
The source can be found here: fakeupload-0.0.2.tgz
#1 by Giorgio Sironi on March 6, 2009 - 11:10 am
Quote
Nice, but I prefer wrap *_uploaded_file() functions in a class that I can mock and redefine $_FILES in userland code.
#2 by Mikko Koppanen on March 6, 2009 - 1:45 pm
Quote
Giorgio,
The code was written by someone else and I had no intention to touch it further
Pingback: Mikko Koppanen’s Blog: Fake uploading files : Dragonfly Networks
#3 by Aljoscha on April 16, 2009 - 1:10 pm
Quote
Hi, this is very useful indeed and works like a charm!
But did you try providing image data file to the fakeupload_file function?
I tried using a base64_decode($base64EncodedImageData) and ‘image/jpeg’ mime type and ended up with a broken image file.
The reason is the usage of fputs for writing the character stream, while the image data can contain characters.
By using fwrite instead, any binary data can be fake uploaded, like so:
— php_fakeupload.c.orig 2009-04-16 12:09:10.865504325 +0200
+++ php_fakeupload.c 2009-04-16 12:06:13.141502707 +0200
@@ -69,7 +69,7 @@
if (!fp) {
error = UPLOAD_ERROR_E;
} else {
- fputs (contents, fp);
+ fwrite (contents, 1, contents_len, fp);
fclose(fp);
}
}
Cheers, Alex
#4 by Mikko Koppanen on April 16, 2009 - 1:30 pm
Quote
Hi Alex,
I never tested binary data. Here is an updated version with the fix you provided: http://valokuva.org/php_ext/fakeupload/fakeupload-0.0.2.tgz
#5 by Mike on May 23, 2009 - 11:25 pm
Quote
Hi, nice posts there
thank’s for the interesting information
#6 by Nick on May 25, 2009 - 9:21 am
Quote
Does anyone by chance have a win32 pre-compiled version of this extension?
#7 by Nick on May 26, 2009 - 6:14 am
Quote
Ignore my previous question. I was able to successfully compile this extension using Microsoft Visual C++ 2008 Express (configured via steps provided on TalkPHP) and ensuring that COMPILE_DL_FAKEUPLOAD was defined.
Awesome extension, solved one of my unit testing headaches!
#8 by Mangola on July 12, 2009 - 11:08 am
Quote
I added your blog to Google Reader.
#9 by podarki on August 23, 2009 - 11:06 am
Quote
Вообще, на мой взглÑд, Ñамое лучшее в личном блоге, так Ñто Ñамопознание.
#10 by Ageno on September 3, 2010 - 11:25 pm
Quote
I’ve never read about these functions…
It’s really useful, thanx
#11 by Rhonda on June 30, 2011 - 11:01 pm
Quote
Never even thought of the need for something like this until a few days ago when I too wanted to test an upload controller. This little code bailed me out nicely.
Thanks.
- RD
#12 by Joe on September 11, 2011 - 4:28 am
Quote
Nice code, thank you Mikko!
I used CURL to test my upload forms. Maybe it`s principle will be useful:
$file, “var1″=>$var1, “var2″=>$var2);
$ch = curl_init();
curl_setopt($ch, CURLOPT_VERBOSE, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$result = curl_exec($ch);
curl_close($ch);
echo $result;
?>
#13 by Peter Edgerton on September 30, 2011 - 6:38 pm
Quote
Useful functions! Thanks for sharing them.
#14 by Steffen on November 7, 2011 - 11:29 pm
Quote
Thanks for sharing. The code is really useful.