seblhaire/uploader

A Laravel library to provide file upload utilities. A Javascript library builds a complete file upload widget with upload button, drag-and-drop zone, progress bar and result builder. A controller is available to manage uploaded files.

Installs: 7

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 1

Forks: 0

Open Issues: 0

Language:JavaScript

2.0.3 2021-08-12 19:33 UTC

This package is auto-updated.

Last update: 2021-10-12 19:55:57 UTC


README

By Sébastien L'haire

A Laravel library to provide file upload utilities. A Javascript library builds a complete file upload widget with upload button, drag-and-drop zone, progress bar and result builder. A controller is available to manage uploaded files.

It uses:

Uploader example image

Demo site available here.

Installation

  1. composer require seblhaire/uploader

  2. Composer will automatically link the package with Laravel. But you still can explicitely add provider and facade to your config/app.php:

  'providers' => [
    ...
      Seblhaire\TableBuilder\UploaderServiceProvider::class,
      ...
   ],
   'aliases' => [
        ...
      "TableBuilderHelper" => Seblhaire\TableBuilder\UploaderHelper::class
   ]
  1. Publish package (optionally).
$ php artisan vendor:publish
  1. Set storage link (optionally, see Laravel doc)
$ php artisan storage:link
  1. For Javascript and stylesheets, see next section.

Javascript and stylesheets

On a webpage, every JS library and CSS stylesheets can be linked separately. If you choose this classical way, first dowload and install above mentionned libraries or use Content Delivery Network (CDN) links as in the example page in last section. Then publish package files as explained above and put following tags in your template:

<script type="text/javascript" src="js/vendor/seblhaire/uploader/upload.js"></script>
<link rel="stylesheet" type="text/css" property="stylesheet" href="css/vendor/seblhaire/uploader/uploader.css"/>

But websites often use many libraries and stylesheets and browser must download many files before the site can be rendered properly. Modern websites come with a single compressed Javascript file which concatenates necessary scripts; same principle for stylesheets. With Laravel you can use Laravel Mix to compile files.

Use NPM package manager : npm install bootstrap jquery @fortawesome/fontawesome-free

Then your js source file should be something like this:

global.jQuery = require('jquery');
var $ = global.jQuery;
var jQuery = global.JQuery;
window.$ = $;
window.jQuery = jQuery;
require('bootstrap');
require('../../vendor/seblhaire/uploader/resources/js/uploader.js');

For your stylesheet:

@import '~bootstrap/scss/bootstrap';
@import "~@fortawesome/fontawesome-free/scss/fontawesome";
@import "~@fortawesome/fontawesome-free/scss/regular";
@import "~@fortawesome/fontawesome-free/scss/solid";
@import "~@fortawesome/fontawesome-free/scss/brands";

@import "../../vendor/seblhaire/uploader/resources/css/uploader";

Configuration file

Uploader library is customizable. Default values can be changed, either in configuration file, or by passing options in Facade function (see next section). If you want to modify default configuration file, publish package files and access to config/uploader.php.

Usage

Uploader package comes with a simple Facade.

Link to Facade:

use Seblhaire\Uploader\UploaderHelper;

UploaderHelper::init

Inits a uploader PHP object that can be passed to the view to set the uploader properly.

UploaderHelper::init($uploaderElement, $label, $url, $options = array(), $additionalParams = array())

where:

  • $uploaderElement: id of <div> tag where the uploader must be inserted.
  • $label: field label for uploader
  • $url: route that must be used to upload file. Cf below.
  • $options: array of options.
    • 'draggable': sets drag and drop option. Default true.
    • 'hidden': hide uploader at beginning. Default false.
    • 'uploadzoneclass': class of main uploader div. Default 'uploadzone'.
    • 'acceptable_mimes': comma-separated list of file extensions allowed.
    • 'droptext': text to be displayed in drop zone. Text can be string or translation key. Cf below.
    • 'droptextclass': class of drop zone text, Default: 'form-text'.
    • 'divclass': class for div containig uploader label and button. Default: 'form-row'.
    • 'divcol': class for column div containing label. Default: 'form-group col-md-2'.
    • 'labelclass': class for label. Default 'col-form-label'.
    • 'buttondivclass': class for button div. Default 'col-auto'
    • 'buttonclass': class of upload button. Default: 'btn btn-dark'.
    • 'uploadicon': FontAwesome classes to define button icon. Default: "fas fa-upload".
    • 'uploadtext' text of upload button. Text can be string or translation key. Cf below.
    • 'progbarmainclass': class for main progress bar div. Default: "progress".
    • 'progressbarwidth': width of progress bar. Can be fixed or percentage. Default: '40%'.
    • 'progressbar': progress bar class. Default: "progress-bar progress-bar-striped progress-bar-animated".
    • 'failmessage': message displayed in case of upload failure. Text can be string or translation key. Cf below.
    • 'alerterrorclass': class for alert div displayed in case of failure. Default: 'alert alert-danger'.
    • 'alertsuccessclass': class for alert div in case of success- Default: 'alert alert-success'.
    • 'alerttimeout': time in milliseconds before alert div is hidden. Default: 10000.
    • 'defaultpath': default path where to upload files. Cf below. Default: "/".
    • 'resultclass': upload result processor class. Cf below, Default: 'UploadresultProcessor'.
    • 'errorfn': function to process file upload error if you don't want to use default one. Function name or null. Default null.
    • 'buildresultdivfn': function to build div where to display upload results. Cf below. Default: 'builduploadresultdiv'.
    • 'maxfilesizek': max file size in kilobytes. Default: null.
  • $additionalParams: array of parameters to be sent to routes.

Uploader sends data to a controller (see below) which accepts parameters to set filename, file systems storage name and file path. Since these values are usually set dynamically, Uploader Javascript object provides methods to set them; the PHP object built by our Facade provides methods to insert Javascript code properly, for instance in Ajax scripts.

Set path name

setPath($path, $is_string = true)

  • $path can be a string or a variable name
  • $is_string indicates if $path is a string (true) or a variable (false).

Find further explanation here and usage example here.

Set file name

setfilename($filename)

Name is self explaining. Find further explanation here and usage example here.

Set file system storage name

setstoragename($storagename)

Uploader uses Laravel file system. $storagename must be one of the storage names stored of your application config/filesystems.php. Find further explanation here and usage example here.

Get result processor

getresultprocessor()

After upload success, Uploader returns a Result processor, which is a Javascript object. See details here. You may need to access to the result processor attached to your Uploader, for instance to add files already uploaded in previous processes. In this case, insert following in your view:

var proc = {!! $uploader->getresultprocessor() !!};

Summary

To summarize, in your controller insert:

$uploader = UploaderHelper::init(
  'uploaderdiv',
  'Uploader',
  route('fileupload'),
  [
    'resultclass' => 'UploaderResult'
  ], [ // additional parameters transmitted to second script
    'article_title' => "l'ami",
    'article_id' => 40
]);
...
return view('uploader', ['uploader' => $uploader]);

In your blade template, insert following at the place you want your uploader to appear:

{!! $uploader !!}

If you need to set form parameters or add files in result list, you can use methods shown above. In this case, we insert them in document ready clause but you will generally use it in an Ajax function:

jQuery(document).ready(function(){
  // set uploaders after page is completely loaded
  {!! $uploader->setpath('/uploads') .
  $uploader->setstoragename('public'); !!}
  var proc = {!! $uploader4->getresultprocessor() !!}
  proc.preparedisplay({filename: 'seb.jpg', ext: 'jpg'});
});

Result div builder

Since Uploader is highly customizable, it calls a function to build results zone below uploader div. File resources/js/upload.js contains the following function that is called by default;

builduploadresultdiv = function(divid, filelistid){
  var filelist = jQuery('<ul></ul>')
                  .attr('id', filelistid)
                  .addClass('list-unstyled');
  return jQuery('<div></div>')
                  .attr('id', divid)
                  .append(filelist);
}

divid and filelistid are element id that are defined in Uploader javascript object. If you wish to use another function, you need define a new function that returns a jQuery element and set option buildresultdivfn. In your uploader result class (see next section) you will need to use divid and filelistid to insert your results in div.

Uploader result class

File processing depends strongly on your web app purposes. Therefore it is impossible to provide a complete uploader package that satisfies all needs. We provide useful functions instead.

Uploader uses a result class to deal with upload results returned by controller. Package contains a base result class UploadresultProcessor stored in resources/js/upload.js that can be replaced or extended. You can define your own result class that replaces or extends UploadresultProcessor ,

Mandatory class properties and function are:

  • property uploader. This links a result class instance to its corresponding uploader instance.
  • method init(uploader). It is called by uploader after instance creation in order to set uploader property.
  • method process(res): this function is called to process upload result. In UploadresultProcessor it is defined as follows:
process: function(res){ //  process result of file uploader
    if (res.ok){
      this.uploader.notify(
        this.uploader.options.alertsuccessclass,
        res.filename + ' uploaded'
      );
    } else {
      this.uploader.notify(
        this.uploader.options.alerterrorclass,
        res.message
      );
    }
}

It uses res.ok variable returned by uploader. Note that you can use the uploader notify that sets the alert div set in uploader div.

UploadresultProcessor has two other methods that you can use with the standard result div as in image shown at this document beginning.

  • dothumbnail(ext, url): builds either a FontAwesome image corresponding to file extension ext or a thumbnail of uploaded image. url is the url image on your website. If file is an image, if mouse goes over thumbnail, a greater version of image is displayed in a tooltip. Method returns a jQuery object.
  • addfiletolist(thumbnail, content): insert a new file in list. thumbnail is a jQuery object returned by dothumbnail method. content is another jQuery object that contains for instance filename and other things.

Class extension

Base class provides only base functions and you can easily write your own result processing functions. All you need is to write a class with a process method, to extend base class and to init uploader replacing resultclass with your class name.

Your class extension can be in a js file or placed between <script type="text/javascript"></script> in your view.

UploaderResult = {
  process: function(result){
    if (result.ok){
	var thumb = this.dothumbnail(res.ext, url);
        var content = jQuery('<div></div>')
           .append(jQuery('<h5></h5').addClass('mt-0 mb-1').html(res.filename));
	this.addfiletolist(thumb, content);
...
  }
}

In this example, we use methods dothumbnail and addfiletolist. You can also call an Ajax script to store for instance files in databases or whatever you want.

Finally extend base class: UploaderResult = jQuery.extend({}, UploadresultProcessor, UploaderResult);

Further examples can be found here.

Controller

Uploader package comes with a upload controller that simply uploads a file. The file is stored using Laravel file storage system. It can be stored for instance in public folder to be used in website or in storage system for other purposes.

Four parameters must be sent by file uploader:

  • file: file object transmitted by file uploader, which has useful functions:
    • getClientOriginalName(): returns original name;
    • getMimeType(): returns file MimeType;
    • getSize(): returns file size;
  • storagename: storage name defined in config/filesystems.php (cf Laravel file storage system). If null, filesystem is default.
  • path: path in fileystem, can be empty string.
  • filename: file name for uploaded file:
    • if a name is provided it will replace original file name; if file already exists on target directory, file will be overwritten;
    • if empty, original file name will be used; if file already exists on target, a new file name will be generated.

In most cases, you will need further processing for file. You might for instance store information into tables. In this case, you can either:

  • use your own upload function more or less based on the version in package;
  • or use a second process that can be called after the file is uploaded.

If you want to use package controller, simply add the following to your routes. You can
chose any path and any route name.

Route::post('/fileupload', [Seblhaire\Uploader\FileuploadController::class, 'index'])->name('fileupload');

Translation keys

Laravel loads config files very early in process. Therefore config files cannot contain __('translation.key'). In order to solve this issue, we made an helper either to print directly strings or to send translation key to translation helper. Translation keys can be delimited by character # . Ex: "uploader::messages.uploadtext". Original translations are stored under vendor/seblhaire/uploader/resources/lang. If you publish package files, you can find translations in resources/lang/vendor/uploader/.

Feel free to translate keys in your own language and either to send it to the author or to do a merge request on GitHub.