Downloadable Products Submodule
For Silverstripe Shop
Allows Products and/or ProductVariations to have files attached
that the customer can download once the product has been purchased
and remain available on the user's account pages.
- Silverstripe 3.1+ (may work with 3.0, but hasn't been tested)
- Shop Module 1.0 or master branch
- ZipArchive must be enabled in php for full functionality
- Can be applied to a Product or ProductVariation or both
- If a variation is purchased, all files from both variation and main product
become available for download (can be overridden from the cms).
- Any number and type of file can be associated with a Product
- Downloads are available immediately on receipt screen if paying by credit card
- Downloads are available on the order history
- All historical downloads are available from a central screen in the account area
- Can download files individually or any combination in a zip archive
- We should keep the zip files around for a few days so we don't recreate them all the time
- Cron job to delete old files
- Download links should not be guessable
- Download links should be different for each customer/order for the same file
- Downloads should be logged
- Compatible with markguinn/silverstripe-cloudassets module for storing downloads on CDN
composer require markguinn/silverstripe-shop-downloadable dev-master
- Add Downloadable extension to Product and/or ProductVariation or only to certain subclasses.
- Go add some files in the CMS (each product will have a "Files" tab)
File Download Process
- Once order is paid, files show up on the order screen. Links are generated by the Downloadable extension on
- The link a user clicks is something like "http://example.com/downloads/FILE-HASH", which hits the DownloadController.
- Hash is repeatable given an order ID and file ID (so it will work in emails too)
- This step could also include a form submission with multiple files.
- DownloadController logs the download. If it's only for a single file and the file is small (default 100M, but
configurable via yml) it will just output the mime type and use readfile to immediately initiate the download. If there
is more than one file or if it's a large file, a temporary "Please wait" page will be displayed while the file is copied
and/or zipped if more than one.
- The temporary file will be cached in such a way that it can be re-used until it is deleted by a cron job.
- The text of the temporary page can be taken from any page in the CMS via yml config
- If one wants to disable the "pass through" behaviour entirely it can be easily done by setting the smallfilesize to 0.
- Supports X-Sendfile on servers that have it turned on. In such a case one could probably just set the smallfilesize
very very high since the file will never be in memory.
- If the temporary page is displayed, it will immediately redirect to another URL that will start the copy/zip task
- When the copy/zip task is complete it will redirect to the actual url of the temporary file
Configuration (YML options on Downloadable class)
- tab_name: name of the tab for files in the CMS (default: Downloads)
- source_folder: where are these files uploaded by default in the cms (default: product-files)
- zip_folder: location of temporary zip files and large file copies (default: temp-order-files)
- downloadlinkbase: URL segment for links - e.g. http://example.com/downloads/filekey (default: downloads)
- smallfilesize: anything below this will be passed on directly via readfile or x-sendfile with no temp file created (default: 100M)
- usexsendfile: use the X-Sendfile header instead of readfile, must have modxsendfile (or equivalent) installed (default: false)
- crunching_page: url segment/path of a page to display instead of the default while copying/zipping files
- crunchingzombiewindow: how many minutes before crunching is restarted on a zip file (default: 5)
- deletetempfiles_after: how many hours before the temp files are ok to delete (default: 48)
Would be nice but I have no intention of doing the work myself anytime soon:
- Time limit on downloads
Contributions welcome by pull request and/or bug report.
Please follow Silverstripe code standards.
Copyright (c) 2013 Mark Guinn
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is furnished to do so, subject
to the following conditions:
The above copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.