/** * SWI-Prolog fine uploader demo * * Author: Jan Wielemaker * License: This file is in the public domain */ :- module(fine_upload_demo, [ run/0 ]). :- use_module(library(http/thread_httpd)). :- use_module(library(http/http_server_files)). :- use_module(library(http/http_dispatch)). :- use_module(library(http/http_path)). :- use_module(library(http/html_head)). :- use_module(library(http/html_write)). :- use_module(library(http/js_write)). :- use_module(library(broadcast)). :- use_module('../prolog/http/fine_uploader'). % Uncomment to see some progress debug. % :- debug(upload). /** Fine file upload demo This module demonstrates the Fine file uploader integration. The server backend is in `../prolog/http/fine_uploader.pl`. This file builds an example web page. We considered wrapping all this in a library, but the almost infinite number of configuration and deployment options makes this a doubtful enterprice. This file is placed in the public domain such that you can freely copy/paste from it. Note that the notably the style and template HTML is subject to the fine uploader license. @see https://docs.fineuploader.com/endpoint_handlers/traditional.html */ %! run % % start the server at port 8080 run :- http_server(http_dispatch, [port(8080)]). %! handle_upload(+File, +Path, +Request) is det. % % The uploading of a file was completed. The file is in Path and was % named File on the user's machine. Request is the full HTTP request. :- listen(file_upload(File, Into, Request), handle_upload(File, Into, Request)). handle_upload(File, Into, Request) :- size_file(Into, Size), option(peer(Peer), Request), format(user_error, "File ~p has been uploaded to ~p (~D bytes from ~p)~n", [File, Into, Size, Peer]). % Define the JS and CSS as a resource to simplify including it using % html_requires//1. :- html_resource( fine_uploader, [ virtual(true), requires([ js('fine-uploader.js'), css('fine-uploader-new.css') ]) ]). :- http_handler(root(.), home, []). %! home(+Request) % % Emit the demo welcome page at / home(_Request) :- reply_html_page( title('Fine Uploader -- SWI-Prolog backend'), [ h1('Fine Uploader -- SWI-Prolog backend'), \fine_uploader ]). %! fine_uploader// % % Emit the file uploader. This consists of the header elements, % template, style, the uploader itself and finally the script that % combines it all. fine_uploader --> html_requires(fine_uploader), fine_template, fine_style, html(div(id('fine-uploader-manual-trigger'), [])), fine_script. %! fine_script// % % Emit the script that links all parts together. Note that we first % use http_link_to_id/3 and http_absolute_location/3 to find the % endpoint locations for this service. fine_script --> { http_link_to_id(fine_uploads, [], UploadURL), http_link_to_id(fine_upload_finished, [], FinishedURL), http_link_to_id(fine_upload_delete, [], DeleteURL), http_absolute_location(icons(.), IconURL, []) }, js_script({|javascript(UploadURL,FinishedURL,DeleteURL,IconURL) || var manualUploader = new qq.FineUploader({ element: document.getElementById('fine-uploader-manual-trigger'), template: 'qq-template-manual-trigger', request: { endpoint: UploadURL }, thumbnails: { placeholders: { waitingPath: IconURL+'/placeholders/waiting-generic.png', notAvailablePath: IconURL+'/placeholders/not_available-generic.png' } }, deleteFile: { enabled: true, endpoint: DeleteURL, method: 'DELETE' }, chunking: { enabled: true, success: { endpoint: FinishedURL, jsonPayload: true } }, autoUpload: false, debug: true, folders: true, validation: { allowedExtensions: ["pdf", "html", "jpg", "jpeg", "png"], acceptFiles: "application/pdf,text/html,image/jpeg,image/png" } }); qq(document.getElementById("trigger-upload")).attach("click", function() { manualUploader.uploadStoredFiles(); }); |}). %! fine_style// % % Define additional styles fine_style --> html({|html|| |}). /******************************* * TEMPLATE AND FILES * *******************************/ %! fine_template// % % Emit the template for the file uploader. Tried to use a `src` in the % script, but that only seems to work for JavaScript script elements. % We now read the script and inject it directly. fine_template --> { read_file_to_string(template('fine-uploader.html'), Template, []) }, html(script([ type('text/template'), id('qq-template-manual-trigger') ], \[Template])). % Configure locations of the files where we can find web resources :- multifile http:location/3. % Alias, Expansion, Options :- dynamic http:location/3. % Alias, Expansion, Options http:location(template, root(template), []). user:file_search_path(web, web). user:file_search_path(template, web(template)). user:file_search_path(js, web(js)). user:file_search_path(css, web(css)). user:file_search_path(icons, web(icons)). :- http_handler(template(.), serve_files_in_directory(template), [prefix]).