As you know HTML5/Flash Uploader sends files and additional metadata from client computers to server side in HTTP POST requests. This approach requires server script to parse the received requests and handle uploaded data. Reading this topic you will get to know how to extract files and additional data sent by clients, save it all to file system on a server or handle in some other way. There are three approaches to perform this task:
If you parse requests using PHP predefined variables and enable sending files by chunks you will have to write significant amount of non-trivial server-side code to assembly the files on your server. This way, we do not recommend enabling chunks if you use this method of handling requests.
For versions of PHP earlier than 6.0 disable the magic_quotes_gpc
directive in your php.ini
file.
Further in this topic every approach will be described in detail. Let us start with the UploadHandler class description.
All the HTML5/Flash Uploader PHP classes are located in the /ImageUploaderFlashPHP/
folder. The key class is UploadHandler, which allows processing the data uploaded
from client computers. This class has user-friendly API and functionality giving flexible typed access to these data.
In order to use UploadHandler you have to include
UploadHandler.class.php
into your upload handling script (see: Quick Start with HTML5/Flash Uploader PHP),
for example, upload.php
:
<?php require_once "ImageUploaderFlashPHP/UploadHandler.class.php"; $handler = new UploadHandler(); ?>
And specify URL to this script as a value of the UploadSettings.ActionUrl property (both absolute and relative URLs are supported) like it is shown below:
<?php $uploader->getUploadSettings()->setActionUrl("upload.php"); ?>
This section describes the simplest way of handling uploaded data - autosave. This approach allows you to save all the uploaded files to the specified folder on your server without writing a lot of code. The UploadHandler class described in the previous section can save uploaded files automatically. You just create a new instance of this class in your upload handling script and call its saveFiles(string) method providing a path to the folder where uploaded files should be saved as a parameter. If the specified folder does not exist HTML5/Flash Uploader tries to create it.
If you need to process the saved files in some way, then a page specified in the UploadSettings.RedirectUrl setting is the right place for this. Just put your code there and it will be executed after the upload process is completed.
The example below shows how to save all the uploaded files.
The upload.php
file:
<?php require_once "ImageUploaderFlashPHP/UploadHandler.class.php"; $handler = new UploadHandler(); $handler->saveFiles("Catalog/"); ?>
And a script initializing the ImageUploaderFlash object must contain the following code:
<?php $uploader->getUploadSettings()->setActionUrl("upload.php"); ?>
HTML5/Flash Uploader prepares files on client side in the way set by converters. Each converter specifies
what to do with a file selected for upload: upload it as is or apply some transformation before upload (resize image down, extract and send icon
associated with a file, or compress a file to ZIP format). Converters
(except for SourceFile
one) add suffixes to file names uploaded to a server. For example, the
name.ext_Thumbnail0.ext
filename is the result of applying Mode="*.*=Thumbnail"
converter on name.ext
file. For a full list of possible suffixes see the ConvertedFile.Name property description.
Filenames collisions may occur while saving uploaded files to a destination folder.
If the destination folder already has a file with the same name as uploaded one,
the uploaded file will be saved under its name appended by _xx
, where xx
is a number
starting from 2
. For example, if there is a file with the name name.ext
in the destination folder and a user tries
to upload another file with the same name then uploaded file is saved as name_02.ext
file. If
name_02.ext
file exists as well then the recently uploaded file gets name_03.ext
filename and so on.
This approach requires quite a bit of code, however, this method is more flexible than autosave described before. The main idea is to handle uploaded files and data in the callback functions specified by FileUploadedCallback and/or AllFilesUploadedCallback settings of the mentioned before UploadHandler class. The first function is called each time a user-specified file is successfully uploaded. The second function is called when the whole upload session completes and all the files, metadata, and additional data are received on the server side. The first one is called as many times as number of files selected for upload, whereas the second one is called only once.
Now, when you understand the differences between these events, let us discuss how to create these event handlers. There are two steps to this process:
There is a requirement for the callback functions - they must have an argument, which gets an UploadedFile or an UploadedFile array value. The following example sets both, FileUploadedCallback and AllFilesUploadedCallback, callback functions, and enables request processing by calling the processRequest() method:
<?php require_once "ImageUploaderFlashPHP/UploadHandler.class.php"; $handler = new UploadHandler(); $handler->setFileUploadedCallback("saveUploadedFile"); $handler->setAllFilesUploadedCallback("saveAllUploadedFiles"); $handler->processRequest(); function saveAllUploadedFiles($uploadedFiles) { //... foreach ($uploadedFiles as $uploadedFile) { //... } //... } function saveUploadedFile($uploadedFile) { //... } ?>
There is the example of callback function implementation below.
Also do not forget to set the UploadSettings.ActionUrl property.
For better understanding let us separate description of the uploaded data handling into the following sections:
The PHP server-side part of HTML5/Flash Uploader among its types has the UploadedFile class. This type holds all the data associated with a single file selected for upload (files prepared on client side by HTML5/Flash Uploader from the original file in accordance with converters set in the settings, additional fields, and other data). The FileUploadedCallback callback function gives access to an UploadedFile instance through the function argument. The AllFilesUploadedCallback callback function gives access to an array of UploadedFile objects also via its argument.
Now let us examine how to get access to uploaded files via the UploadedFile instances. Each UploadedFile object has associated collection of files prepared by HTML5/Flash Uploader converters on client side. Each of these files is represented by an instance of the ConvertedFile type. This way, the collection of converted files associated with a particular file selected for upload is accessible via the UploadedFile.ConvertedFiles property.
Each ConvertedFile object has two main members to handle the file:
All the metadata uploaded along with a file is accessible through the UploadedFile properties and can be divided into the following groups:
This group includes properties containing information about the original file:
The ConvertedFile class provides access to some additional information along with access to the converted file itself. Its properties contain the following information:
This group includes the following properties:
This example is a FileUploadedCallback callback function which saves an original file and its
resized copy to the ../Gallery/
and ../Gallery/Thumbnails/
folders respectively and writes
some file-related information (filenames, image dimensions, user description, and etc.) to an XML file. This function is called only once when
the whole upload session completes as it is set by the AllFilesUploadedCallback property.
<?php function saveAllUploadedFiles($uploadedFiles) { $galleryPath = "Gallery/"; $absGalleryPath = realpath($galleryPath); $absThumbnailsPath = realpath($galleryPath . DIRECTORY_SEPARATOR . "Thumbnails/"); //Create or load XML file which will keep information about files (image dimensions, description, etc). $descriptions = new DOMDocument('1.0'); if (file_exists($absGalleryPath . DIRECTORY_SEPARATOR . "Descriptions.xml")) $descriptions->load($absGalleryPath . DIRECTORY_SEPARATOR . "Descriptions.xml"); else $descriptions->appendChild($descriptions->createElement("files")); foreach ($uploadedFiles as $uploadedFile) { $convertedFiles = $uploadedFile->getConvertedFiles(); //Save original file. //It is the first file in ConvertedFiles collection as we set first converter mode to SourceFile. $sourceFile = $convertedFiles[0]; getSafeFileName($absGalleryPath, rawurlencode($uploadedFile->getSourceName())); $sourceFile->moveTo($absGalleryPath . DIRECTORY_SEPARATOR . $sourceFileName); //Save thumbnail. //It is the second file in ConvertedFiles collection as we set second converter mode to Thumbnail. $thumbnailFile = $convertedFiles[1]; $thumbnailFileName = getSafeFileName($absThumbnailsPath, rawurlencode($uploadedFile->getSourceName())); $thumbnailFile->moveTo($absThumbnailsPath . DIRECTORY_SEPARATOR . $thumbnailFileName); //Save file info. $xmlFile = $descriptions->createElement("file"); $xmlFile->setAttribute("name", $sourceFileName); $xmlFile->setAttribute("thumbName", $thumbnailFileName); $xmlFile->setAttribute("width", $uploadedFile->getSourceWidth()); $xmlFile->setAttribute("height", $uploadedFile->getSourceHeight()); $xmlFile->setAttribute("description", $uploadedFile->getDescription()); $descriptions->documentElement->appendChild($xmlFile); } $descriptions->save($absGalleryPath . DIRECTORY_SEPARATOR . "Descriptions.xml"); } function getSafeFileName($path, $fileName) { // ... } ?>
The last way of handling uploaded files is to parse the upload request manually via the $_FILES
and $_POST "superglobals". Before parsing the upload request should be converted to the standart RFC1867 format.
To perform it you should link the flashrequestfix.php
with the upload page and call the
preProcessRequest(). There are two more functions in flashrequestfix.php
:
If you do not call the postProcessRequest() function, temporary files will be accumulated on your server.
If you choose this approach we do not recommend enabling chunks, otherwise, you will have to write significant amount of non-trivial server-side code to assembly the files on your server.
To simplify accessing the POST request fields HTML5/Flash Uploader PHP provides the PostFields class. The following code sample demonstrates how to save original files, thumbnails, and original file-related information using described approach.
Server-side upload script should return a non-empty response.
<?php require_once "ImageUploaderFlashPHP/PostFields.class.php"; require_once 'ImageUploaderFlashPHP/flashrequestfix.php'; preProcessRequest(); $galleryPath = "Gallery"; $absGalleryPath = realpath($galleryPath); $absThumbnailsPath = realpath($galleryPath . DIRECTORY_SEPARATOR . "Thumbnails"); //Create or load XML file which will keep information about files (image dimensions, description, etc). $descriptions = new DOMDocument('1.0'); if (file_exists($absGalleryPath . DIRECTORY_SEPARATOR . "Descriptions.xml")) $descriptions->load($absGalleryPath . DIRECTORY_SEPARATOR . "Descriptions.xml"); else $descriptions->appendChild($descriptions->createElement("files")); $originalFileName = rawurlencode($_POST[sprintf(PostFields::sourceName,0)]); //save source file $sourceFileName = getSafeFileName($absGalleryPath, $originalFileName); if (isset($_FILES[sprintf(PostFields::file, 0, 0)])) { moveFile($_FILES[sprintf(PostFields::file, 0, 0)]["tmp_name"], $absGalleryPath . DIRECTORY_SEPARATOR . $sourceFileName); } //save thumbnail file $thumbnailFileName = getSafeFileName($absThumbnailsPath, $originalFileName); if (isset($_FILES[sprintf(PostFields::file, 1, 0)])) { moveFile($_FILES[sprintf(PostFields::file, 1, 0)]["tmp_name"], $absThumbnailsPath . DIRECTORY_SEPARATOR . $thumbnailFileName); } //Save file info. $xmlFile = $descriptions->createElement("file"); $xmlFile->setAttribute("name", $sourceFileName); $xmlFile->setAttribute("thumbName", $thumbnailFileName); $xmlFile->setAttribute("width", $_POST[sprintf(PostFields::sourceWidth, 0)]); $xmlFile->setAttribute("height", $_POST[sprintf(PostFields::sourceHeight, 0)]); $xmlFile->setAttribute("description", $_POST[sprintf(PostFields::description, 0)]); $descriptions->documentElement->appendChild($xmlFile); $descriptions->save($absGalleryPath . DIRECTORY_SEPARATOR . "Descriptions.xml"); postProcessRequest(); // Server-side upload script should return a non-empty response. echo "complete"; function getSafeFileName($path, $fileName) { // ... } ?>
Also do not forget to set the UploadSettings.ActionUrl property.