In the following example we are going to take a simple product and add a file option to it to see how the file is being handled by the system.
Our test product is “The Get Up Kids: Band Camp Pullover Hoodie (Shirts T)” from the Magento sample data (download). Its SKU is 4fasd5f5. We would like to allow customers to upload an image file to be printed on the shirt. Open this product in the back-end and switch to the Custom Options tab. The list of options is empty. Click the “Add New Option” button in the upper right corner. In the form that appears select File in the “Input Type” drop-down list. The form must look like this:
Enter the following values into the form fields:
- Title: Print
- Is Required: yes
- Price: leave blank so that uploading a print file doesn’t change the product price
- SKU: leave blank, our example doesn’t require this option to be a unique SKU
- Allowed File extensions: png, jpg, jpeg, bmp, tiff, tif, gif – a string of the most common image file extensions, comma separated.
- Maximum Image Size: since we are expecting images, enter 1024 by 1024 px. For non-image file options these two fields should be left blank.
Save the product and open it in the front-end. You will see that the product details page now has an additional form to upload the required print image option.
Since we have indicated the Print option as required, you can’t add this product to the shopping cart unless a file is uploaded. The validation options we set in the back-end mandate that this file must be an image file with one of the allowed extensions and dimensions not exceeding the 1024 by 1024 pixel limit.
Let’s try to find out how this limitations are enforced by uploading a text file instead of an image. Select any file with a “txt” extension and click “Add to Cart”.
Before a product can be added to the cart its options must be processed. This functionality is provided by Product Type models. The base product type functionality is defined in class Mage_Catalog_Model_Product_Type_Abstract. Some products type, such as configurable or bundle extend it for their specific purposes, but in a case of a simple product this class covers all the required functions. Thus, product options are taken care of in method Mage_Catalog_Model_Product_Type_Abstract::_prepareOptions. It goes through all the options defined for the product and validates the user input for them. Since we are testing an option of type “File” the validation is performed in method Mage_Catalog_Model_Product_Option_Type_File::_validateUploadedFile. In our example the uploaded file is checked against three constraints:
- File extension must be in one of the image file extensions we’ve provided (case insensitive).
- Image dimensions must not exceed 1024 by 1024 pixel
- File size must not exceed the server setting for upload_max_filesize and post_max_size (the lowest value of the two).
Naturally, the validation fails as the “txt” doesn’t match the allowed image extensions.
Now, go ahead and upload any image file with a proper extension.
The uploaded custom option files are stored in the directory custom_options under the shop’s media folder. If such directory doesn’t exist yet, it is created automatically. The custom_options has two sub-directories order and quote to where the uploaded file will be placed in.
Once uploaded, the file remains in the media/custom_options/quote folder. If you look in there, you’ll notice that the system has created some new sub-directories. This was the work of dispersion (Varien_File_Uploader::getDispretionPath): uploaded files are arranged into a directory structure, which consist of two nested folders each with a 1 character name. If your file is called “test.gif”, it will be placed under t/e/ path. The folder names correspond to the first and the second characters of the file name.
The uploaded file doesn’t retain its original name for security reasons, of course. For the same reasons the directories the file is uploaded into are made inaccessible from the outside, i.e. you cannot link directly to the file. The file, however, can be downloaded. You can see a link to it in the shopping cart overview. The link is provided by the Mage_Sales module’s download controller. Remarkably, the link can be opened without checking user credentials, which poses a security risk. Beware if some customer decides to use your shop as a file sharing service!
After the order is placed the file is copied to the media/custom_options/order folder, where it again is placed under the dispersion sub-folders.
That’s it, the uploaded file is a part of the order now as an item option. You can access the item options by calling Mage_Sales_Model_Order_Item::getProductOptions(). The result is an array, whose element “options” contains an array of all item options. The link to the file can be found there under the key “value”:
[options] => array(1) (  => array(7) ( [label] => (string) Print [value] => (string) <a href="https://comm170.solvingmagento.dev/sales/download/downloadCustomOption/id/42/key/74d35b7205b48e5f07e1/" target="_blank">1.gif</a> 718 x 799 px. [print_value] => (string) 1.gif 718 x 799 px. [option_id] => (string) 3 [option_type] => (string) file [option_value] => (string)