Upload files via AJAX and fill up other model properties in the same time
There’s a comment to Yii 1.1: XUpload Workflow Wiki article, made by MeDroogie, who asks, how to handle situation, where file is correctly uploaded (via AJAX, in separate layer, handled by upload action), but form submission itself fails, as form processing action stops on some model’s validation errors.
I had the same problem with other AJAX uploader, that I think, I solved gracefully.
Keep in mind, that since solution, that I’m discussing in this article, is part of proprietary project, I cannot share any code. This is purely design or theoretical discussion.
After testing few solutions and approaches, I figured out that the best is to split upload process into two steps. I’m in the beginning of using this particular extension, so I’m not sure yet, if I can use the same approach with it (it worked just perfect with previous uploader, but I had to quit using it due to licensing limitations).
My model save process starts from upload step. User uploads file. Upload action moves file to final destination and creates new model (record in DB) with path pointing to just uploaded file. It does not set any other model’s property. It then returns result to browser.
This first-step action runs in “create” scenario only. It never updates new record.
I intercept return result (in Javascript, on client side) from upload widget. If upload is successful, I use the same Javascript to route page to second step, where user fills out all other fields (for example enters meta-data for uploaded file, adds tags etc.). This second-step action goes always in “update” scenario only. It never creates new model.
If return results, after upload completed, indicates an error:
- upload-time error,
- problem related to moving file from temporary folder to final destination,
- any error coming from creating model etc.,
then I display that error and do not redirect browser anywhere.
If user cancels second step, not saving entire model fields, or never reach it due to some error, then this will create an “orphan” record in the DB — i.e. the one with assigned file, but without other fields filled out.
Daily run CRON task is developed to handle such records.
It is fired from time to time (manually or via CRON) and it purges database from all such “orphan” records, deletes all not deleted files in temporary folder and also removes all files from destination folder, if they do not belong to any model in database.