Other versions:

FancyUpload - Swiff meets Ajax (v3.0)

Project FancyUpload - Swiff meets Ajax Showcase Swiff meets Ajax for powerful and elegant uploads. FancyUpload is a file-input replacement which features an unobtrusive, multiple-file selection menu and queued upload with an animated progress bar. It is easy to setup, is server independent, completely styleable via CSS and XHTML and uses MooTools to work in all modern browsers.

Showcases:

Showcase “Attach a File”

A reduced and snappier interface (preview).

The Action Happens Here

Experimental interface preview, not fully tested yet. Inspired by a real-world usage, used in a well-known web-application. Imagine it wrapped in a form to compose e-mails …

Enabled Validations

What will happen?

JavaScript & MooTools

/**
 * FancyUpload Showcase
 *
 * @license		MIT License
 * @author		Harald Kirschner <mail [at] digitarald [dot] de>
 * @copyright	Authors
 */
 
window.addEvent('domready', function() {
 
	/**
	 * Uploader instance
	 */
	var up = new FancyUpload3.Attach('demo-list', '#demo-attach, #demo-attach-2', {
		path: '../../source/Swiff.Uploader.swf',
		url: '../script.php',
		fileSizeMax: 2 * 1024 * 1024,
 
		verbose: true,
 
		onSelectFail: function(files) {
			files.each(function(file) {
				new Element('li', {
					'class': 'file-invalid',
					events: {
						click: function() {
							this.destroy();
						}
					}
				}).adopt(
					new Element('span', {html: file.validationErrorMessage || file.validationError})
				).inject(this.list, 'bottom');
			}, this);	
		},
 
		onFileSuccess: function(file) {
			new Element('input', {type: 'checkbox', 'checked': true}).inject(file.ui.element, 'top');
			file.ui.element.highlight('#e6efc2');
		},
 
		onFileError: function(file) {
			file.ui.cancel.set('html', 'Retry').removeEvents().addEvent('click', function() {
				file.requeue();
				return false;
			});
 
			new Element('span', {
				html: file.errorMessage,
				'class': 'file-error'
			}).inject(file.ui.cancel, 'after');
		},
 
		onFileRequeue: function(file) {
			file.ui.element.getElement('.file-error').destroy();
 
			file.ui.cancel.set('html', 'Cancel').removeEvents().addEvent('click', function() {
				file.remove();
				return false;
			});
 
			this.start();
		}
 
	});
 
});
 

XHTML Markup

<a href="#" id="demo-attach">Attach a file</a>
 
<ul id="demo-list"></ul>
 
<a href="#" id="demo-attach-2" style="display: none;">Attach another file</a>

PHP Script

<?php
/**
 * Swiff.Uploader Example Backend
 *
 * This file represents a simple logging, validation and output.
 *  *
 * WARNING: If you really copy these lines in your backend without
 * any modification, there is something seriously wrong! Drop me a line
 * and I can give you a good rate for fancy and customised installation.
 *
 * No showcase represents 100% an actual real world file handling,
 * you need to move and process the file in your own code!
 * Just like you would do it with other uploaded files, nothing
 * special.
 *
 * @license		MIT License
 *
 * @author		Harald Kirschner <mail [at] digitarald [dot] de>
 * @copyright	Authors
 *
 */
 
 
/**
 * Only needed if you have a logged in user, see option appendCookieData,
 * which adds session id and other available cookies to the sent data.
 *
 * session_name('SID'); // whatever your session name is, adapt that!
 * session_start();
 */
 
// Request log
 
/**
 * You don't need to log, this is just for the showcase. Better remove
 * those lines for production since the log contains detailed file
 * information.
 */
 
$result = array();
 
$result['time'] = date('r');
$result['addr'] = substr_replace(gethostbyaddr($_SERVER['REMOTE_ADDR']), '******', 0, 6);
$result['agent'] = $_SERVER['HTTP_USER_AGENT'];
 
if (count($_GET)) {
	$result['get'] = $_GET;
}
if (count($_POST)) {
	$result['post'] = $_POST;
}
if (count($_FILES)) {
	$result['files'] = $_FILES;
}
 
// we kill an old file to keep the size small
if (file_exists('script.log') && filesize('script.log') > 102400) {
	unlink('script.log');
}
 
$log = @fopen('script.log', 'a');
if ($log) {
	fputs($log, print_r($result, true) . "\n---\n");
	fclose($log);
}
 
 
// Validation
 
$error = false;
 
if (!isset($_FILES['Filedata']) || !is_uploaded_file($_FILES['Filedata']['tmp_name'])) {
	$error = 'Invalid Upload';
}
 
/**
 * You would add more validation, checking image type or user rights.
 *
 
if (!$error && $_FILES['Filedata']['size'] > 2 * 1024 * 1024)
{
	$error = 'Please upload only files smaller than 2Mb!';
}
 
if (!$error && !($size = @getimagesize($_FILES['Filedata']['tmp_name']) ) )
{
	$error = 'Please upload only images, no other files are supported.';
}
 
if (!$error && !in_array($size[2], array(1, 2, 3, 7, 8) ) )
{
	$error = 'Please upload only images of type JPEG, GIF or PNG.';
}
 
if (!$error && ($size[0] < 25) || ($size[1] < 25))
{
	$error = 'Please upload an image bigger than 25px.';
}
*/
 
 
// Processing
 
/**
 * Its a demo, you would move or process the file like:
 *
 * move_uploaded_file($_FILES['Filedata']['tmp_name'], '../uploads/' . $_FILES['Filedata']['name']);
 * $return['src'] = '/uploads/' . $_FILES['Filedata']['name'];
 *
 * or
 *
 * $return['link'] = YourImageLibrary::createThumbnail($_FILES['Filedata']['tmp_name']);
 *
 */
 
if ($error) {
 
	$return = array(
		'status' => '0',
		'error' => $error
	);
 
} else {
 
	$return = array(
		'status' => '1',
		'name' => $_FILES['Filedata']['name']
	);
 
	// Our processing, we get a hash value from the file
	$return['hash'] = md5_file($_FILES['Filedata']['tmp_name']);
 
	// ... and if available, we get image data
	$info = @getimagesize($_FILES['Filedata']['tmp_name']);
 
	if ($info) {
		$return['width'] = $info[0];
		$return['height'] = $info[1];
		$return['mime'] = $info['mime'];
	}
 
}
 
 
// Output
 
/**
 * Again, a demo case. We can switch here, for different showcases
 * between different formats. You can also return plain data, like an URL
 * or whatever you want.
 *
 * The Content-type headers are uncommented, since Flash doesn't care for them
 * anyway. This way also the IFrame-based uploader sees the content.
 */
 
if (isset($_REQUEST['response']) && $_REQUEST['response'] == 'xml') {
	// header('Content-type: text/xml');
 
	// Really dirty, use DOM and CDATA section!
	echo '<response>';
	foreach ($return as $key => $value) {
		echo "<$key><![CDATA[$value]]></$key>";
	}
	echo '</response>';
} else {
	// header('Content-type: application/json');
 
	echo json_encode($return);
}
 
?>

CSS Stylesheet

a.hover {
	color: red;
}
 
#demo-list {
	padding: 0;
	list-style: none;
	margin: 0;
}
 
#demo-list .file-invalid {
	cursor: pointer;
	color: #514721;
	padding-left: 48px;
	line-height: 24px;
	background: url(assets/error.png) no-repeat 24px 5px;
	margin-bottom: 1px;
}
#demo-list .file-invalid span {
	background-color: #fff6bf;
	padding: 1px;
}
 
#demo-list .file {
	line-height: 2em;
	padding-left: 22px;
	background: url(assets/attach.png) no-repeat 1px 50%;
}
 
#demo-list .file span,
#demo-list .file a {
	padding: 0 4px;
}
 
#demo-list .file .file-size {
	color: #666;
}
 
#demo-list .file .file-error {
	color: #8a1f11;
}
 
#demo-list .file .file-progress {
	width: 125px;
	height: 12px;
	vertical-align: middle;
	background-image: url(../../assets/progress-bar/progress.gif);
}
 

This example and the accompanying sources/assets are © 2008-2009 by Harald Kirschner and available under The MIT License. For debugging and profiling the scripts and their markup download Firefox and use addons like Firebug and Web Developer Toolbar.

Share it: Stumble it!Digg This!del.icio.us (2121 Posts: )

discussion by DISQUS 1231 Comments

Please use the support forums for discussing the project, asking questions or posting bug-fixes!

Sort:
Comments 1 – 20 of 1231:
  • reply
    Avatar
    said 1 year ago (2 Points)
    Flash 10 is now a problem - will there be an update to this soon?
  • reply
    Avatar
    asdf
    replied 1 year ago (1 Point)
    asdf
  • reply
    Avatar
    replied 1 year ago (1 Point)
    nevermind, I see it
  • reply
    Avatar
    Adrian
    said 2 years ago (2 Points)
    KM:

    Try this; add the session id to the action attribute in the form, e.g. <form action="myFile.php?PHPSESSID=...">
    In myFile.php try this:


    session_start();
    session_name($_GET[session_name()]);

    ?>

    This will set the old session name from the first file, should work.

    - Adrian</form>
  • reply
    Avatar
    StefanTotoescu 2 Points
    said 2 years ago (2 Points)
    If you need to use this in ASP.NET, there is a cool implementation in the SharpPieces suite available at http://www.codeplex.com/SharpPieces

    Cheers
  • reply
    Avatar
    Nacho Garcia
    said 2 years ago (2 Points)
    Hi Harald, i've just uploaded my website using fancyupload and i have seen this problem and dont know why its happening:
    when you visit the website without the www., if i initilized the uploader with the url http://website.com /... doesnt work (cant connect and so its allways 0%), but if i initialized it with the url http//:www.website.com/... it works.

    So if i initialize uploader with / without " www. ", users will be able to upload their files when visiting the website with / without " www. " respectively

    thanks for your work !!
  • reply
    Avatar
    said 2 years ago (2 Points)
    Do you have any version for the asp.net users? (-:
    just the PHP part to replace.
  • reply
    Avatar
    replied 2 years ago (1 Point)
    Just put this in Page_Load:
    foreach (string fileKey in HttpContext.Current.Request.Files)
    {
    HttpPostedFile file = HttpContext.Current.Request.Files[fileKey];
    file.SaveAs(Server.MapPath("/Files/" + fileName));
    }

    Also you need to modify the Javascript to tell the action of the form, since the ID is made up by ASP.NET
  • reply
    Avatar
    digitarald Site Owner
    replied 2 years ago (1 Point)
    You can access the file like the usual uploaded file, the default field name (option *fieldName*) is "Filedata", u can rename it with that option. I added that question to the FAQ.
  • reply
    Avatar
    Bodom78 5 Points
    said 2 years ago (2 Points)
    Started playing with the script and all worked off the bat locally just the the supplied example.

    How can I call some of the other functions like "onSelect" or "onCancel"?

    Sorry if it's obvious but I'm not too familiar with Mootools.

    Basically I want to call upload when someone selects a file.

    Cheers
  • reply
    Avatar
    digitarald Site Owner
    replied 2 years ago (1 Point)
    In the current preview API you have to extend it or edit the class itself (mark edits with your signature so u see what u changed for later updates). Thats you can extend it:

    var myUploader = new Class(

    Extends: FancyUpload2,

    onSelect: function(file, index, length) {
    this.parent(file, index, length); // currently not needed, onSelect just contains a debug log
    $('big-red-alert').highlight();
    }
    });
  • reply
    Avatar
    Bodom78 5 Points
    replied 2 years ago (1 Point)
    Hey Harald,

    Thanks for that, I wasn't familiar with extending classes but after some reading around I got to understand it and was able to successfully extend on the Fancyupload2 functions like the example you supplied.

    Cheers.
  • reply
    Avatar
    lookatthosemoose 1 Point
    said 2 years ago (2 Points)
    sorry for the comment spam, here's the code for initializing FancyUpload2 w/ a form as additional data:

    FancyUpload2($(‘demo-status’), $(‘demo-list’), {
    ‘url’: $(‘form-demo’).action,
    ‘data’: $(‘upload_ticket’), //will convert the form to query string.
    ‘fieldName’: ‘upload’,
    ‘path’: ‘swiff/Swiff.Uploader.swf’,
    ‘onLoad’: function() {
    $(‘demo-status’).removeClass(‘hide’); $(‘demo-fallback’).destroy();
    }
    });
  • reply
    Avatar
    digitarald Site Owner
    replied 2 years ago (1 Point)
    I can clean that up ... [**markdown-documentation**](http://daringfireball.net/projects/markdown/syntax). (btw, disqus allows editing your own comments and you are registered)
  • reply
    Avatar
    philmeaux 1 Point
    said 1 year ago (1 Point)
    i am not great with the javascript, but fairly dangerous with most else. i am working your fancy uploader into my site where it renames and moves the files, when they "Remove" I need to destroy those files and make other changes to data rows. I know it calls a function called "onFileRemove" but I am not sure where it fires off identifying data to and how to fire off php with that click of the "Remove" link. Can you give me some help? Thanks, am intermediate, been working to integrate this for a day now LOL.
  • reply
    Avatar
    Ian
    said 1 year ago (1 Point)
    hey. The stop() method doesn't (seem to) work. I've got a "cancel" link that should abort uploads in progress... so I call uploader.stop()

    nothing stops, the thing just keeps on uploading.

    how do I get it to work?
  • reply
    Avatar
    Rana Ssalim
    said 1 year ago (1 Point)
    in fancy upload how can i adjust file limit size ?
    please any body know tell me.
    when i upload a file and file size is greater than file limit size then show a error message before uploading.?
  • reply
    Avatar
    reffer 1 Point
    said 1 year ago (1 Point)
    Great job! I suggest separate the wonderfull class of upload from the layout objects, giving the data separated like file_name, file_size insted of writing it to a element formated and remove references to Fx.ProgressBar from the class, some people would like a simple html progressbar. It can make easy integrate in other systems. and progress can be show in diferent ways. Thanks!!!
  • reply
    Avatar
    digitarald Site Owner
    replied 1 year ago (1 Point)
    If you use only Swiff.Uploaderyou'll get a vanilla upoader without any layout.
Comments 1 – 20 of 1231:

Post your comment

Please use the support forums for discussing the project, asking questions or posting bug-fixes!


Internet Consultant & Contractor

I'm available to combine forces with you and your team to find the most simple, elegant and convenient web solutions . I await your call.

If you just like my work and want to say Thank You, donate via PayPal or Amazon Wish List.

Developer Resources & Tools