Jump to content
kongondo

Module: Jquery File Upload

Recommended Posts

JqueryFileUpload
 
This module is a ProcessWire implementation of the awesome Blueimp jQuery File Upload plugin.  Server-side, the module provides a custom uploads' handler enabling you to perform various tasks with ease. The module is an interface of the feature-rich Ajax File Uploads widget provided by the jQuery File Upload plugin.
 
The module is completely customisable and can be used both in the front- and backend (e.g. in a third-party module). 
 
Please read the README  carefully and completely before using the module
 
Release Status: Stable
Module Download: http://modules.processwire.com/modules/jquery-file-upload/
Issues tracker Project page: GitHub
 
Security
The module has been written with security in mind and makes no assumptions about any client-side validation. Instead, the module provides robust server-side validation of uploaded files. Server-side, no Ajax requests are honoured unless specifically set via configurable options server-side. This means that client-side requests to upload, delete and list files are not executed unless allowed server-side. By default, files are uploaded to a non-web-accessible (system) folder and files previously uploaded on the server are not sent back for display unless that setting is enabled. However, developers are still strongly advised to implement any other feasible measures to guard against malicious uploads, especially if allowing frontend uploading. For instance, developers can use native ProcessWire checks to limit access to the widget (e.g. only allowing uploads by registered/logged-in users).
 
Demo
A short video demo can be found here (and below :-))(CSS is WIP!  :-)). In the backend, you can see it in action within the (upcoming) module Media Manager
 
Features

  •  Fast Ajax uploads.
  •  Client and server-side validation.
  •  Client-side image resizing (highly configurable options).
  •  Beautiful touch-responsive image gallery preview.
  •  Audio and video previews pre-upload.
  • Chunked and resumable file uploads (currently client-side only; server-side handling planned).
  •  Drag and drop support.
  •  Copy and paste support (Google Chrome only).
  •  Progress bars.
  •  Cross-domain uploads.
  •  Single or multiple uploads.
  •  Delete uploaded files.

Documentation
On GitHub. Have a look at the long list of available options.
 
License
Released under the MIT license
 
@Credits: Sebastian Tschan
@Thanks: Pete and BernhardB for the idea.
 
Please test and provide feedback. Thanks!
 

  • Like 32

Share this post


Link to post
Share on other sites

Man - you aren't just on fire at the moment, you are ablaze :)

Nice work - I have used Blueimp on some other projects pre-PW and loved it, so thank you!

  • Like 1

Share this post


Link to post
Share on other sites

Your timing is impeccable - just what I need today! :)

Share this post


Link to post
Share on other sites

Man - you aren't just on fire at the moment, you are ablaze :)

Nice work - I have used Blueimp on some other projects pre-PW and loved it, so thank you!

3 AM blues!

  • Like 1

Share this post


Link to post
Share on other sites

I finally made it to work on frontend - didn't notice 'disableUploads' => true in the example ... should read more carefully

Share this post


Link to post
Share on other sites

Testing again on IIS with PW3. After upload I don't have access to uploaded files. I get HTTP 500.50 error along with 0x80070005 and that is (from my experience) permission issue. I'm assuming (didn't look at your sources) that files are uploaded to temp directory (PHP's upload_tmp_dir?) and then moved/renamed to the final destination at /site/assets/files/jqfu/files. In the process of moving the files, permissions of the files are inherited from the temp directory and those are not sufficient for the web server. Would you consider using $config->$uploadTmpDir instead of PHP's upload_tmp_dir?

Edit: I see you are using WireUpload class so I'll have to take a closer look into WireUpload.php...

Edited by matjazp

Share this post


Link to post
Share on other sites

PHP stores the uploaded file in the folder determined by upload_tmp_dir directive in php.ini. By default this is C:\Windows\Temp directory. After the uploaded file is stored to the upload_tmp_dir, ProcessWire will then move/rename the file to the final destination directory and that doesn’t inherit destination directory’s permissions. There are multiple options on how to make it work:
 
a.) Change the permissions on the windows temp folder giving IUSR and IIS_IUSRS  write/modify
b.) Change the path of the upload_tmp_dir in the php.ini file to a folder with appropriate permissions
c.) Change the way WireUpload works so that it copy the file, not rename/move it.
 
I didn't have upload problems in admin, because I used $config->$uploadTmpDir pointing to the /site/assets/uploads folder (created by me). This folder is used in WireUpload.php with ajax uploading (using $_SERVER['HTTP_X_FILENAME']). Since /site/assets/uploads folder inherits /site/assets folder permissions, moving/renaming the file is not the problem. When uploading using PHP's $_FILES global variable, $config->$uploadTmpDir is not used and files are uploaded to the folder set up by upload_tmp_dir directive.

As copying in slower than renaming, I'm not sure if this is the right solution (file WireUpload.php in function saveUpload):

$success = move_uploaded_file($tmp_name, $destination);

to:

$success = is_uploaded_file($tmp_name);
if($success) $success = @copy($tmp_name, $destination);
if(is_file($tmp_name)) @unlink($tmp_name);

Share this post


Link to post
Share on other sites

Good forensics. If it's a WireUpload.php issue then you can put in a request with @Ryan to hear his thoughts? Meanwhile, you can always use a custom uploads handler in conjunction with the other methods that come with the module, e.g. getResponse() which calls the crucial validation methods.

Share this post


Link to post
Share on other sites

I've written the issue on GitHub to hear Ryan's thoughts. I'm not good enough in PHP or PW internals and don't know when ajax upload is used. In "ajax mode" uploaded file is read from php://input and then created at the $config->$uploadTmpDir (if set) folder. In "nonajax mode" $config->$uploadTmpDir is not used - files are uploaded to the folder set up by upload_tmp_dir directive in php.ini It would be ideal if "nonajax upload" would store files in $config->$uploadTmpDir to... Is this possible? Sorry for dumb questions...

  • Like 1

Share this post


Link to post
Share on other sites

Do you have the demo without/or different music? The German GEMA and SME had YouTube blocking the video for Germany.  :'(

  • Like 1

Share this post


Link to post
Share on other sites

For a minute there I thought you were kidding. Never heard of this German GEMA & SME thing. I have just quickly read up about it. Well, I could try upload the video to Vimeo (would that work?) or you could do me a favour and watch the YT one behind a proxy :) ...that's not illegal, or is it?

Edit: There's also the 'original' demo at Blueimp

  • Like 1

Share this post


Link to post
Share on other sites

For a minute there I thought you were kidding. Never heard of this German GEMA & SME thing. I have just quickly read up about it. Well, I could try upload the video to Vimeo (would that work?) or you could do me a favour and watch the YT one behind a proxy :) ...that's not illegal, or is it?

I assume this will not work with a simple proxy as it is not that easy to trick google / youtube.

Share this post


Link to post
Share on other sites

I assume this will not work with a simple proxy as it is not that easy to trick google / youtube.

:ph34r:

...I have started the 'slow' upload to vimeo... :'(.... :lol:

  • Like 1

Share this post


Link to post
Share on other sites

Here's the vimeo version. Cannot get 1080p quality unless you are on the paid plans, but its viewable. I don't think am uploading to vimeo again...this was the first and last time. It takes forever and they restrict the quality, tsk.  :-)

  • Like 1

Share this post


Link to post
Share on other sites

It is an awesome video, so, also with music. Have had a nice looking. Thanks man!

Will also try the module in the next time.

  • Like 1

Share this post


Link to post
Share on other sites

Will also try the module in the next time.

Thanks. Will appreciate your professional opinion especially regarding the client-side-image resizing

  • Like 1

Share this post


Link to post
Share on other sites

Firstly - Kongondo - thanks for another great module.

I have been working on this all day and I have the form working well on the frontend, I can upload images and other files and I can see the upload progress etc on screen which is great and exactly what I've been looking for.

Where I've hit a brick wall for the last 3-4 hours though is I can't work out how to attach this to a field on one of my templates.  I have a template where I want to have a field which will allow users to upload images or files via the frontend. I have some other fields in the template too (normal text fields for description etc) and I have had those working for a long time - what I can't work out is how do I take the files uploaded via this jQuery module and add them to the files field in my template???

Any help gratefully received..

Share this post


Link to post
Share on other sites

Hi @Hantsweb,

Glad you like the module.

Technically, you can't 'attach' the module to a field in one of your templates :-). But I think I get what you are saying. You want uploaded files to be added to a field on some page(s). Before I dive into an answer, I hope in your upload implementation you've remembered to...'never to trust your users',...especially those who are allowed to add things to pages and whether what they've uploaded is immediately viewable on the frontend :-). Yes, the module does very thorough validation and will only upload what you've allowed to be uploaded but its always good to double check.

Below are links to some code I've previously posted that will be of help. What is your workflow? Are user uploads immediately added to a page? Are there unique pages for each user? Are compressed files (zip) in play? Whatever the answer to these questions, the basics are the same:

  1. Upload files to your server to a specified temporary folder(s). During the process validate the files: JqueryFileUpload
  2. Iterate over the folder with the uploads: I always use PHP SPL class for this, e.g. RecursiveDirectoryIterator
  3. In each iteration, add valid files to specified pages (if those pages are not being created by the uploads): Use ProcessWire for this
  4. Delete uploads in the temporary folder

Example code:

https://processwire.com/talk/topic/10815-mass-create-pages-or-mass-upload-images-and-thus-create-pages/?p=101791

https://processwire.com/talk/topic/8416-importing-many-pictures-in-a-page/

If you are adding to files to pages directly after they've been uploaded, you will want to listen to Ajax requests sent by JqueryFileUpload like so:

if ($this->config->ajax) {
  // you code here for iteration, creating and/or adding files to pages

}

Let us know if you hit another brick wall :-)

  • Like 1

Share this post


Link to post
Share on other sites

hi kongondo,

if i get you right, this module is intended to be used on frontend, isn't it? in the demo, though, it is used in backend with your media manager. would it be hard to get some kind of replacement of a standard image field directly in the backend? :)

Share this post


Link to post
Share on other sites

hi kongondo,

if i get you right, this module is intended to be used on frontend, isn't it? in the demo, though, it is used in backend with your media manager. would it be hard to get some kind of replacement of a standard image field directly in the backend? :)

:huh:  :huh:   :o  :o  :undecided:   :undecided:  

The module is completely customisable and can be used both in the front- and backend (e.g. in a third-party module).

In the video 0.00 - 4.25 Frontend (check the URL); 4.25 to end Backend (MediaManager)

:-)

As for your question about image replacement: I think it would be easiest to either extend FieldtypeFile or modify FieldtypeImage as a new module (and/or their related Inputfields - am not sure). What exactly are you after? I ask because I know there are some cool changes coming to the 'standard image field' and those might just meet your needs.

Edited by kongondo
  • Like 1

Share this post


Link to post
Share on other sites

thank you and sorry for not reading carefully enough  :-[

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By bernhard
      --- Please use RockFinder3 ---
    • By MoritzLost
      Cacheable Placeholders
      This module allows you to have pieces of dynamic content inside cached output. This aims to solve the common problem of having a mostly cacheable site, but with pieces of dynamic output here and there.  Consider this simple example, where you want to output a custom greeting to the current user:
      <h1>Good morning, <?= ucfirst($user->name) ?></h1> This snippet means you can't use the template cache (at least for logged-in users), because each user has a different name. Even if 99% of your output is static, you can only cache the pieces that you know won't include this personal greeting. A more common example would be CSRF tokens for HTML forms - those need to be unique by definition, so you can't cache the form wholesale.
      This module solves this problem by introducing cacheable placeholders - small placeholder tokens that get replaced during every request. The replacement is done inside a Page::render hook so it runs during every request, even if the response is served from the template cache. So you can use something like this:
      <h1>Good morning, {{{greeting}}}</h1> Replacement tokens are defined with a callback function that produces the appropriate output and added to the module through a simple hook:
      // site/ready.php wire()->addHookAfter('CachePlaceholders::getTokens', function (HookEvent $e) { $tokens = $e->return; $tokens['greeting'] = [ 'callback' => function (array $tokenData) { return ucfirst(wire('user')->name); } ]; $e->return = $tokens; }); Tokens can also include parameters that are parsed and passed to the callback function. There are more fully annotated examples and step-by-step instructions in the README on Github!
      Features
      A simple and fast token parser that calls the appropriate callback and runs automatically. Tokens may include multiple named or positional parameters, as well as multi-value parameters. A manual mode that allows you to replace tokens in custom pieces of cached content (useful if you're using the $cache API). Some built-in tokens for common use-cases: CSRF-Tokens, replacing values from superglobals and producing random hexadecimal strings. The token format is completely customizable, all delimiters can be changed to avoid collisions with existing tag parsers or template languages. Links
      Github Repository & documentation Module directory (pending approval) If you are interested in learning more, the README is very extensive, with more usage examples, code samples and usage instructions!
    • By Craig
      I've been using Fathom Analytics for a while now and on a growing number of sites, so thought it was about time there was a PW module for it.
      WayFathomAnalytics
      WayFathomAnalytics is a group of modules which will allow you to view your Fathom Analytics dashboard in the PW admin panel and (optionally) automatically add and configure the tracking code on front-end pages.
      Links
      GitHub Readme & documentation Download Zip Modules directory Module settings screenshot What is Fathom Analytics?
      Fathom Analytics is a simple, privacy-focused website analytics tool for bloggers and businesses.

      Stop scrolling through pages of reports and collecting gobs of personal data about your visitors, both of which you probably don't need. Fathom is a simple and private website analytics platform that lets you focus on what's important: your business.
      Privacy focused Fast-loading dashboards, all data is on a single screen Easy to get what you need, no training required Unlimited email reports Private or public dashboard sharing Cookie notices not required (it doesn't use cookies or collect personal data) Displays: top content, top referrers, top goals and more
    • By daniels
      This is a lightweight alternative to other newsletter & newsletter-subscription modules.
      You can find the Module in the Modules directory and on Github
      It can subscribe, update, unsubscribe & delete a user in a list in Mailchimp with MailChimp API 3.0. It does not provide any forms or validation, so you can feel free to use your own. To protect your users, it does not save any user data in logs or sends them to an admin.
      This module fits your needs if you...
      ...use Mailchimp as your newsletter / email-automation tool ...want to let users subscribe to your newsletter on your website ...want to use your own form, validation and messages (with or without the wire forms) ...don't want any personal user data saved in any way in your ProcessWire environment (cf. EU data regulation terms) ...like to subscribe, update, unsubscribe or delete users to/from different lists ...like the Mailchimp UI for creating / sending / reviewing email campaigns *I have only tested it with PHP 7.x so far, so use on owners risk
      EDIT:
      Since 0.0.4, instructions and changelog can be found in the README only. You can find it here  🙂
      If you have questions or like to contribute, just post a reply or create an issue or pr on github, thanks!
    • By MoritzLost
      Sorry for the convoluted title. I have a problem with Process modules that define a custom page using the page key through getModuleInfo (as demonstrated in this excellent tutorial by @bernhard). Those pages are created automatically when the module is installed. The problem is that the title of the page only gets set in the current language. That's not a problem if the current language (language of the superuser who is installing the module) is the default language; if it isn't, the Process page is missing a title in the default language. This has the very awkward effect that a user using the backend in the default language (or any other language) will see an empty entry in the setup menu:

      This screenshot comes from my Cache Control module which includes a Process page. Now I realize the description sounds obscure, but for us it's a common setup: We a multiple bilingual sites where the default language is German and the second language is English. While the clients use the CMS in German, as a developer I prefer the English interface, so whenever I install a Process module I get this problem.
      As a module author, is there a way to handle this situation? I guess it would be possible to use post-installation hooks or create the pages manually, but I very much prefer the declarative approach. The page title is already translatable (through the __ function), but of course at the time of installation there is no translation, and as far as I'm aware it's not possible to ship translations with a module so they are used automatically. Could this situation be handled better in the core? I would prefer if the module installation process would always set the title of the Process page in the default language, instead of the language of the current user.
×
×
  • Create New...