Implementation of fully functional media uploading in web application - php

Suppose we have the web application which handle create, read, update and delete articles and each article should have gallery of images. I have to make one to one relation between Article and Gallery and one to many relation between Gallery and Media.
HTML5 gives a lot of features like multiupload, so I want to use this excellent http://blueimp.github.io/jQuery-File-Upload/ plugin for that. The problem is how to handle the file upload "in memory" like other form's data?
For example when we show the page for create new article we should be able to fill in article's data fields and select images to upload, next when we click the save button the images should start upload and after that the form should submit. When validation fails the images should be still displayed on the frontend, but on the server-side nothink should be saved.
One of the solutions is create somethink like "create entity session temporary id" before displaying the entire form and that id can be used to create temporary directory for save uploads, so after success saved form these images can be moved to appropriate directory, but how to make the "create entity session temporary id"?
The other solution I think is the "with the edit id" approach, because we can handle the uploads with previously saved gallery id, but sometimes I can't save new blank article with gallery, cause some of the fields should't be empty in db.
For the Rails I saw https://github.com/thoughtbot/paperclip gem which in the Readme says:
Paperclip is intended as an easy file attachment library for Active Record. The intent behind it was to keep setup as easy as possible and to treat files as much like other attributes as possible. This means they aren't saved to their final locations on disk, nor are they deleted if set to nil, until ActiveRecord::Base#save is called.
My question is how it works?

The problem with enabling file uploads on the create mask is that you eventually end up with orphaned files. This is because a user is able to trigger the upload without saving the actual entity. While creating a very own UploadBundle I thought about this problem for a while and came to the conclusion that there is no truly proper solution.
I ended up implementing it like this:
Given the fact that our problem arise from orphaned files, I created an Orphanage which is in charge of managing these files. Uploaded files will first be stored in a separate directory, along with the session_id. This helps distinguishing files across different users. After submitting the form to create the actual entity, you can retrieve the files from the orphanage by using only your session id. If the form was valid you can move the files from the temporary orphanage directory to the final destination of your files.
This method has some pitfalls:
The orphanage directory itself should be cleaned on a regular basis using a cron job or the like.
If a user will upload files and choose not to submit the form, but instead start over with a new form, the newly uploaded files are going to be moved in the same directory. Therefore you will get both the files uploaded the first time and the second time after getting the uploaded files.
This is not the ultimate solution to this problem but more of a workaround. It is in my opinion however cleaner than using temporary entities or session based storage systems.
The mentioned bundle is available on Github and supports both Orphanage and the jQuery File Uploader plugin.
1up-lab/OneupUploaderBundle

I haven't work with the case personaly, but my co-worker had similar conundrum. She used
punkave/symfony2-file-uploader-bundle
It's a bundle that wrapps jQuery File Upload plugin. It is in the early stages and a lot of things are missing, such as event, but we gave it a shot.
That's what we do: in newAction() we create entity, generate unique dir ID, and store the ID in entity (via regular setDirId()). Than we create the form, which contains hidden field dirId.
We are uploading the files to temp dir on server via ajax, not during the submit. Ajax request requires the ID. It stores files in temp_dir/prefix_ID
Than it's quite simple. Form is sent. If form is valid - move files from temp to dest dir. If not - we have the ID, and are able to show the images.
However, we do not save information about individual files in a separate table in the database. Every time we read the contents of the folder that corresponds to our dirId.
I know it's not the solution You are asking for. It's rather a workaround.

Related

October CMS - Remove file attachments with unsaved model

I'm trying to create a front-end AJAX file uploader for a form and everything is working perfect, except for one issue.
I used deferred binding to enable uploading before the record is created in DB.
In a rare scenario, when someone uploads a file and doesn't send the form the record is not created, but the attached file still exists.
I don't know if there is a build-in solution for this problem is October CMS.
A better example is RainLab Blog Plugin. If you try a new post and add a featured image but not save the post and close the tab, the post doesn't create but the file remains in storage/app/uploads/public.
I was thinking of writing an scheduled task to delete unbinded files, but don't know how to detect them.
Does anyone have a solution for this issue?
you can look at the table:
system_files
and the ones without a
attachment_id or/and
attachment_type or/and
field
are unused maybe the media table should be cleaned too.

Is there any mechanism in Laravel 5 to delete unused uploaded files?

There are situations where a user uploads a file (say image field inside a form) but doesn't save the form and simply close the browser. It causes unused files to reside inside the server.
In some CMSs like Drupal there is a mechanism to detect such files and delete them after a while. They create a table called file_managed, and for every uploaded file, they assign the id of the content which it belongs to. So it is easy to find unused files.
I would like to know is there any mechanism like this in Laravel that detects the unused uploaded files?
thanks.
The selected file won't be uploaded if form is not submitted. In case of ajax upload, place the file in any temporary folder first, when the user completes the form and submits it, move the uploaded picture to the correct path and remove it from the temporary folder.
You can write some cron jobs or queues to empty the temporary folder
I know its an old post, but to update it to more recent solution to this problem (Laravel 8 at this time) --> this video helped me: https://www.youtube.com/watch?v=Vs4EQqFcD-c

Using oneuploader in a form with other fields

I would like to use the OneUploader bundle in a Symfony2 form that also contains other fields. In other words, the uploaded file is handled as an attachment to the rest of the data in the form. But I can only find instructions on how add the uploader as a separate form with it's own controller to which the files are sent. So how do I handle the use case I just described?
Bundle dev here.
Frontend uploaders like jQuery File Upload or Dropzone always forge a seperate request when uploading a file to the server. This means that the upload process takes place before the form handling in your controller. If you really want to upload file along with the main form request, then you should not use such an uploader. Instead, create an Entity Media (or the like) map it to the base entity with a OneToMany or ManyToMany association and add it to the form with an Entity type.
There are some pretty good answers here on StackOverflow, for example this one.
However, if you choose to not use a frontend uploader all your files will be sent to the server simultaneously. Depending on the file size / server configuration this can result in upload errors. Moreover the upload will not be performed asynchronously anymore, which forces the user to wait for the upload to complete, after he submitted the form.
There is general problem when dealing with asynchronous multiple uploads on creation forms. I tried to answer a similiar question here.
The problem with enabling file uploads on the create mask is that you eventually end up with orphaned files. This is because a user is able to trigger the upload without saving the actual entity.
Your problem seems like a good use case for the Orphanage feature of this bundle. It lets you upload files before an actual entity exists to attach these files to. After the main form has been submitted you can retrieve the files and perform some more logic on top of it.
Note: This is by no means a perfect solution. Take a look at the limitations! Summarized can be said; as this feature is based on the session, a user may end up having uploaded a file twice. Be sure to handle this accordingly.
And then there is the possibility that you just want to add some more data to the file upload request: As this is handled in the frontend uploader, it differs from implementation to implementation. For example the jQuery File Uploader just serializes the whole form and sends along all other values, including hidden fields.
Personal Recommendation: I'd not send the file along with the form submit request. Instead use a frontend uploader and either:
Let users upload files not until the entity exists where it should be attached. This is a quite common strategy and in most cases the desired one. A simple second step when creating an entity should be sufficient.
Take a look at the Orphanage feature if you really want to be able to upload files directly on the creation mask.

upload image, then put file path into a form

I just need a bit of advice on what direction to go with something I am creating.
It is a simple php based webpage for our sports and social members in our office, allowing them to create, edit, view and delete events for all members to see. Events like day trips, bbq's and all kinds of things like that.
So far I have it all working as I would like, other than one thing, being the event logos.
At present, the events are all stored in a mysql database, in one table, with a column for every aspect of the event; time, date, price, venue etc etc.
I also have two columns for the event logos, one for the venue logo, and one for the general event logo.
What I need advice on, is the best way to create a page that allows a user to upload an image to the server, browse the images already uploaded, select one, and have it's file path entered into a text input when creating the event.
Could someone offer their suggestions on the best way to go about this, or offer an alternative method for selecting and inputting a logo for the event?
Thanks
The Uploadify jQuery plugin works really well for batch and/or AJAX uploads. The way I'd handle your situation would be this:
Show all images on the same page with the form, and give each image a related radio button with the image path as the button's value, so the user simply checks the image they want to use,
If the user wants to upload images, use the Uploadify plugin and it's AJAX callback functions to dynamically populate the existing list of radio buttons.
The comment I made on your question, asking wether you store images (or their file paths) was because I think it would be much easier (and cleaner) for you to retrieve a list of uploaded images by querying a database. Personally, I don't store images in a database, only their file paths, and use PHP to handle any images that need to be deleted or moved. It's easier to assing images to other entities (especially in many-to-many relationships) that way.
If you don't want to store images' data in a separate table, I guess you'd have to use PHP file system functions to get a list of files already uploaded (glob comes to mind, although there could be better functions or this).
EDIT:
There is also a very good AJAX file browser plugin - ckFinder, but I have very little experience with it and can't really comment on its workflow, but if you find it to be a more elegant solution, you should try it out.
if i could understand your question you want to associate the image with the event i.e tag the image with the event right ??
you can use jquery's attr() function to grab the src of img and put it in input field
I ended up storing the images in the database itself.
Saved some hassle on the file path side of things.

what are the best practices for letting users upload theme files to my server

I'm trying to make my own framework for my own projects and I would want people to upload themes for their profiles to the database. Letting them theme the look and feel of their accounts.
I first thought of having the files on the server.
A user would log in and the PHP would pick up their user id and other misc details and route the urls to their particular folder and serve the files in that folder.
an example would be a real directory of
http://www.foo.bar/users/me/style.css
http://www.foo.bar/users/me/script.js
http://www.foo.bar/users/me/index.tpl
http://www.foo.bar/users/me/otherPage.tpl
then I was thinking wow, imagine if I have 100's of users? then I would have 100's of folders in my users directory on my server, not to mention duplicate files all over the place taking up space. So ok, while this may be the fasted way to fetch a file maybe loading the markup from the database won't be such a bad idea right?
My server looks cleaner but now my database will get queried a lot more than I would want.
Then comes the major issue i think, is having files that are particular to a user. For example stylesheets may have background url's with images, so now these images needed to be linked to their real path on the server. Which brings me back to having a dedicated folder for each user to house their theme specific files.
How can i securely and effectively find a way to let users upload themes and have all files images, pdf's, docs, etc. all saved without them potentially being accessed by another account holder or thru simple hacking techniques to pull a file from the server that belongs to another user.
One solution I thought of was to only let users who are logged in view files, append to the file a unique tag that will let the user view the file if the tag matches a session variable. But then what if a user wants to share that file with another person, then tagging the file would bring my back to square 1 with the security thing not letting view the file because they wouldn't be an authorized user.
Well in any case, what would be best practices to get some of my concerns on the right path to being delt with.
P.S.
I choose these tags because in my solutions I think they will touch upon some of these aspects.
You can store html or css in a table row but be sure to sanitize the data to avoid hacks, or injections. The easiest way would be to let the user paste the code into a text area or field. If you want to let them upload files, you will need to write a script that parses the data from the uploaded file. This is more complicated as you will have to manage all filtering and sanitizing along with making pulling the data from the file and saving it to the database.
We skin our CMS to work with multiple clients and their own users. But rather than giving them the possibility of changing ANY area or style of the page we allow certain areas such as:
upload your logo
set the colour of the banner bar behind your logo (using a smart colour picker and some 'figure out the contrast between the colours' functions)
set your text colour (using a colour picker)
and so on for the items you want them to change.
We then store those in the database and serve them up through dynamic stylesheets (I know these don't cache but it's better than having hundreds of files).
I know that MySpace used to let you upload a whole host of HTML and CSS (not sure if they still do) but it's a security nightmare as the potential for XSS is enourmous.
You may want to look at HTML Purifier if you're going to let them add their own custom HTML and full themes -> http://www.htmlpurifier.org

Categories