I found several solutions after browsing around google trying to find a multi-file uploader built around php. Most of these solutions for multi-file uploading fit into one of these three categories.
- Use Flash to upload the images. (The browser only supports one image at a time) –SWFUpload
- Use Javascript to add multiple file type fields, while hidding previous fields – the-stickman
- Use Javascript and hidden iframes embedded on the same page to upload the images. –ajaxf1
I decided to take pieces of the mentioned methods and come up with a solution that worked for me.
Here is the idea behind what we are going to be doing.
- Create a HTML form which has a file upload field
- Set the target of this HTML form to an iFrame which is on the same page
- Have Javascript submit the form everytime the “file” field changes
- Javascript hides the form when submitted, and displays an “animation”
- PHP takes the uploaded file, thumbnails it, and stores the image data
- Javascript unhides the form, and re-hides the animation when upload is complete
- Javascript and php show the thumbnail on the same page right after it was uploaded
This makes this little script appear like an ajax application. It is NOT actually AJAX, but uses css, iframes, php sessions, and javascript to make it appear so.
I’ll try to explain what is happening at each step, but keep in mind, I’m not an expert programmer like my fellow co-workers, and I borrowed most of the work from the mentioned sources above. If you just want to download all the files and take the easy way out, skip to the bottom of the post.
Steps 1 & 2 & 3 – Make Our Form
1
2
3
4
5
6
7
8
9
| <form name="pictureform" action="upload.php" method="post" enctype="multipart/form-data" target="upload_target" >
<p id="f1_upload_process">Loading...<br/><img src="loader.gif" /><br/></p>
<p id="f1_upload_form" align="center"><br/>
<label>Add Pictures:
<input name="myfile" type="file" size="30" onchange="startUpload();document.pictureform.submit();" />
</label>
</p>
<iframe id="upload_target" name="upload_target" src="#" style="width:0;height:0;border:0px solid #fff;"></iframe>
</form>
|
Explanation of the mentioned code:
enctype="multipart/form-data"
Tells the browser you are submitting files, or images with your form.
onchange="startUpload();document.pictureform.submit();
The onchange event of the input field calls the function startUpload(), which will hide the form, and show the animation while uploading. The document.pictureform.submit(); Submits the form to our “action” which we have as “upload.php”
Step 4 – Make the JavaScript functions for hiding and showing
1
2
3
4
5
| function startUpload(){
document.getElementById('f1_upload_process').style.visibility = 'visible';
document.getElementById('f1_upload_form').style.visibility = 'hidden';
return true;
}
|
Explanation of the mentioned code:
By giving our HTML elements id tags,such as id=f1_upload_process
we make them available for manipulation by JavaScript via the DOM.
document.getElementById('f1_upload_process').style.visibility = 'visible';
says: “get the element in the document that has an id of “f1_upload_process” and make it visible.”
This then turns on the visibility of our “animation”
block which we have set “invisible” by default in our CSS file. The opposite occurs for the form block, we make it “invisible” or “hidden.”
Step 5 – Create our “upload.php” script to handle thumbnail and copy image to filesystem
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
| <?php
// keep our session
session_start();
// Check the upload file type
$filetype = $_FILES['myfile']['type'];
$gd_function_suffix = array(
'image/pjpeg' => 'JPEG',
'image/jpeg' => 'JPEG',
'image/gif' => 'GIF',
'image/bmp' => 'WBMP',
'image/png' => 'PNG',
'image/x-png' => 'PNG'
);
$function_suffix = $gd_function_suffix[$filetype];
// Build Function name for ImageCreateFromSUFFIX
if(!$function_suffix){
$err = "Unsupported file type, must be JPG|PNG|GIF|BMP";
}
else{
$function_to_read = 'ImageCreateFrom' . $function_suffix;
// Get the image and create a thumbnail
$img = $function_to_read($_FILES['myfile']['tmp_name']);
if (!$img) {
$err = "could not create image handle";
}
$width = imageSX($img); // Get the image width
$height = imageSY($img); // Get the image height
if (!$width || !$height) {
$err = "No Width or Height";
}
// Build the thumbnail
$target_width = 100; // Thumnail width
$target_height = 100; // Thumbnail height
$target_ratio = $target_width / $target_height; //New target ratio
$img_ratio = $width / $height; // Original ratio
if ($target_ratio > $img_ratio) {
$new_height = $target_height;
$new_width = $img_ratio * $target_height; // Tall Image
} else {
$new_height = $target_width / $img_ratio; // Wide Image
$new_width = $target_width;
}
if ($new_height > $target_height) {
$new_height = $target_height;
}
if ($new_width > $target_width) {
$new_height = $target_width;
}
$new_img = ImageCreateTrueColor($target_width, $target_height); // Create a new image handle for thumbnail
$white = imagecolorallocate($new_img, 255, 255, 255); // Allocate the color white
if (!@imagefilledrectangle($new_img, 0, 0, $target_width-1, $target_height-1, $white)) { // Fill the image white
$err = "Couldn't fill image";
}
// Copy the uploaded image to the newly created image
if (!@imagecopyresampled($new_img, $img, ($target_width-$new_width)/2, ($target_height-$new_height)/2, 0, 0, $new_width, $new_height, $width, $height)) {
$err = "couldn't copy new image";
}
// Create php Session array for image information
if (!isset($_SESSION["file_info"])) {
$_SESSION["file_info"] = array();
}
// Use a output buffering to load the image into a variable
ob_start();
imagejpeg($new_img);
$imagevariable = ob_get_contents();
ob_end_clean();
// Create a unique id or name for the image
$file_id = md5($_FILES["myfile"]["tmp_name"] + rand()*100000);
$new_name = $file_id.".$function_suffix";
$temp_name = $_FILES["myfile"]["tmp_name"];
// assign upload directory, and target path for image
$uploaddir = getcwd(); //
$target_path = $uploaddir.DIRECTORY_SEPARATOR.$new_name;
// Move uploaded image to uploaddir location
if(!@move_uploaded_file($temp_name, $target_path)){
$err = "Couldn't Copy File to Filesystem";
}
// Create a Session array with name, type, and image object for use in displaying thumbnails
if (!isset($_SESSION["file_info"][$file_id])) {
$_SESSION["file_info"][$file_id] = array( "name" => $new_name, "type" => $function_suffix,
"obj" => $imagevariable );
}
}
// If no error, then pass good result and file id to Javascript for generating the thumbnail.
// Pass our $err varialbe along
if(!$err){
$result = "'1','".$file_id."'";
}
else{
$result = "'.$err.','".$file_id."'";
}
sleep(1); // in case of really fast upload, sleep script to show loading animation for a bit longer
// Javascript calls the "stopUpload" function with its paramaters
?>
<script language="javascript" type="text/javascript">window.top.window.stopUpload(<?php echo $result; ?>);</script>
|
Explanation of Code:
These php functions make use of the GD library. You must have that enabled in PHP in order to use this. Also make sure your current directory is writeable.
I won’t explain to many things here, as the code has inline comments. You could make this code a function and have it thumbnail and save multiple sizes to the filesytem. Currently it simply thumbnails a 100 X 100 and copies the original to the current directory the script is running from. It will do GIF, JPEG, BMP, or PNG. Error checking and Session handling could be improved.
Step 6 – Create JavaScript function to show form, and hide animation when upload is finished
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| function stopUpload(success,fileid){
var result = '';
if (success == 1){
result = '<span class="msg">The file was uploaded successfully!<\/span><br/><br/>';
addImage("thumbnail.php?id=" + fileid);
}
else {
result = '<span class="emsg">There was an error during file upload!' + success + '<\/span><br/><br/>';
}
document.getElementById('f1_upload_process').style.visibility = 'hidden';
document.getElementById('f1_upload_form').innerHTML = result + '<label>File: <input name="myfile" type="file" size="30" onchange="startUpload();document.pictureform.submit();" /><\/label>';
document.getElementById('f1_upload_form').style.visibility = 'visible';
return true;
}
|
Explanation of Code:
From our upload.php script, we passed two varialbes to this JavaScript function, Success and File Id.
If we had a successful file upload, we throw up a message saying “success” and call another function called addImage("thumbnail.php?id=" + fileid);
<- More on this later...
If we didn't have a successful upload, we return a message saying so.
The last few lines of the function hide the "animation" bar, and recreate our form input element so we can upload another image, and do the whole thing over again. All without leaving the page!
Step 7 – Our Thumbnail.php script and our addImage() Javascript function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| <?php
// This script accepts an ID and looks in the user's session for stored thumbnail data.
// It then streams the data to the browser as an image
session_start();
$image_id = isset($_GET["id"]) ? $_GET["id"] : false; // get the id from the URL
if ($image_id === false) {
exit(0);
}
if (!is_array($_SESSION["file_info"]) || !isset($_SESSION["file_info"][$image_id])) {
}
header("Content-type: image/jpeg") ;
header("Content-Length: ".strlen($_SESSION["file_info"][$image_id]));
echo $_SESSION["file_info"][$image_id][obj];
exit(0);
?>
|
Code Explanation:
This bit of code simply gets the image id from the URL and pulls the image thumbnail data we saved into our session in our upload.php script, and outputs the image to the browser.
addImage() Javascript Function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| function addImage(src) {
var newImg = document.createElement("img");
newImg.style.margin = "5px";
document.getElementById("thumbnails").appendChild(newImg);
if (newImg.filters) {
try {
newImg.filters.item("DXImageTransform.Microsoft.Alpha").opacity = 0;
} catch (e) {
// If it is not set initially, the browser will throw an error. This will set it if it is not set yet.
newImg.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + 0 + ')';
}
} else {
newImg.style.opacity = 0;
}
newImg.onload = function () {
fadeIn(newImg, 0);
};
newImg.src = src;
}
function fadeIn(element, opacity) {
var reduceOpacityBy = 5;
var rate = 30; // 15 fps
if (opacity < 100) {
opacity += reduceOpacityBy;
if (opacity > 100) {
opacity = 100;
}
if (element.filters) {
try {
element.filters.item("DXImageTransform.Microsoft.Alpha").opacity = opacity;
} catch (e) {
// If it is not set initially, the browser will throw an error. This will set it if it is not set yet.
element.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + opacity + ')';
}
} else {
element.style.opacity = opacity / 100;
}
}
if (opacity < 100) {
setTimeout(function () {
fadeIn(element, opacity);
}, rate);
}
}
|
Code Explanation:
I borrowed most of this code from the SWFUpload project. The basic idea is that we create a new image tag via javascript, give it a src of “thumbnail.php?id=XXXXX” XXXXX being our image name, and call a “fadeIn” function which does just that, fade the image in for a lovely effect. I have this javascript included in my index.php page via
<script type="text/javascript" src="handlers.js"></script>
Thats it! Hope you learned as much as I did from this tutorial.
Important Notes:
-This script does not check file size, or limit the number of files that can be uploaded.
-You will need to add in appropriate error checking on the uploaded files for security.
-You will want to clean out the data from the session when done with the uploading.
-Make sure you have write permission the directory where images are being saved
-You must have GD library installed for this script to work
This entry was posted on Tuesday, July 22nd, 2008 at 4:08 pm and is filed under JavaScript, PHP.
June 3rd, 2008 at 4:55 pm
June 9th, 2008 at 12:27 pm