Skip to content

Commit

Permalink
Change GPL license version from 3 to 2 or later. Improved php example…
Browse files Browse the repository at this point in the history
…, added coldfusion example
  • Loading branch information
Andrew Valums committed Aug 11, 2010
1 parent b75b9f2 commit e9f2200
Show file tree
Hide file tree
Showing 8 changed files with 406 additions and 847 deletions.
2 changes: 1 addition & 1 deletion .gitignore
@@ -1,4 +1,4 @@
/server-side/uploads
/server/uploads/*

.*
Thumbs.db
Expand Down
2 changes: 1 addition & 1 deletion client/fileuploader.js
Expand Up @@ -4,7 +4,7 @@
* Multiple file upload component with progress-bar, drag-and-drop.
* © 2010 Andrew Valums andrew(at)valums.com
*
* Licensed under GNU GPL.
* Licensed under GNU GPL 2 or later, see license.txt.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
Expand Down
899 changes: 282 additions & 617 deletions license.txt

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion readme.md
Expand Up @@ -19,7 +19,7 @@ providing good user experience everywhere.
* supports IE6-8, Firefox 3-4beta, Safari4-5, Chrome, Opera

### License ###
This plugin is open sourced under <a href="http://www.gnu.org/copyleft/gpl.html">GNU GPL</a>.
This plugin is open sourced under <a href="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPL 2</a> or later.
If this license doesn't suit you contact andrew (at) valums.com for another options.

Please [donate][donation_link] if you are willing to support the further development of file upload plugin.
Expand Down
1 change: 1 addition & 0 deletions server/coldfusion/coldfusion.cfc
@@ -0,0 +1 @@
<cfcomponent hint="I handle AJAX File Uploads from Valums' AJAX file uploader library"> <cffunction name="upload" access="remote" output="false" returntype="void"> <cfargument name="qqfile" type="string" required="true"> <!--- get the http request data, use Firebug in Firefox to see the raw http header data ---> <cfset x = GetHttpRequestData()> <!--- write the contents of the http request to a file. The filename is passed with the qqfile variable ---> <cffile action="write" file="#ExpandPath('.')#/#arguments.qqfile#" output="#x.content#" > <!--- if you want to return some JSON you can do it here. I'm just passing a success message ---> <CFCONTENT TYPE="text" RESET="Yes"><cfoutput>{success:true} <cfsetting showdebugoutput="false" /></cfoutput><cfabort> </cffunction> </cfcomponent>
Expand Down
1 change: 1 addition & 0 deletions server/coldfusion/demo.cfm
@@ -0,0 +1 @@
<!DOCTYPE html><html><head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link href="fileuploader.css" rel="stylesheet" type="text/css"> <style> body {font-size:13px; font-family:arial, sans-serif; width:700px; margin:100px auto;} </style> </head><body> <h1>ColdFusion File Uploader Demo</h1> <p><a href="http://github.com/valums/file-uploader">Back to project page</a></p> <p>To upload a file, click on the button below. Drag-and-drop is supported in FF, Chrome.</p> <p>Progress-bar is supported in FF3.6+, Chrome6+, Safari4+</p> <div id="file-uploader-demo1"> <noscript> <p>Please enable JavaScript to use file uploader.</p> <!-- or put a simple form for upload here --> </noscript> </div> <script src="fileuploader.js" type="text/javascript"></script> <script> function createUploader(){ var uploader = new qq.FileUploader({ element: document.getElementById('file-uploader-demo1'), action: '/valums/server/coldfusion/coldfusion.cfc', params: {method: 'upload'} }); } // in your app create uploader as soon as the DOM is ready // don't wait for the window to load window.onload = createUploader; </script> </body></html>
Expand Down
9 changes: 9 additions & 0 deletions server/coldfusion/readme.txt
@@ -0,0 +1,9 @@
Coldfusion example by Sidney Maestre
http://www.designovermatter.com/post.cfm/ajax-file-uploader-for-coldfusion

1. Unzip Andrew's AJAX Uploader into your web root.
2. Replace the demo.htm with demo.cfm in the "client" folder
3. Place coldfusion.cfc in the "server" folder
4. Browse to the demo.cfm file and try it out. The file should be written to the "server" folder.

Questions? You can contact Sidney Maestreme by mail (sid.maestre(at)designovermatter.com) or Twitter @SidneyAllen
337 changes: 110 additions & 227 deletions server/php.php
@@ -1,243 +1,126 @@
<?php
/**
* @license GPL2
* @version 0.9
* @brief Base class for file uploads
* <code>
* //Only allow images to be uploaded
* $validTypes = array('jpeg', 'png', 'jpg', 'gif', 'bmp');
* //determine what kind of upload we are getting from the client
* if (isset($_GET['qqfile'])) {
* $file = new UploadFileXhr($validTypes);
* } elseif (isset($_FILES['qqfile'])) {
* $file = new UploadFileForm($validTypes);
* } else {
* $result = array('success' => FALSE, 'error'=> 'No files were uploaded.');
* }
*
* if(empty($result)){
* $result['success'] = $file->handleUpload('uploads/');
* $result['error'] = $file->getError();
* }
* // to pass data through iframe you will need to encode all html tags
* echo htmlspecialchars(json_encode($result), ENT_NOQUOTES);
* </code>
*/
abstract class Uploader {
/**
* The valid extensions for this uploader (like jpeg, xml, bmp, xls...)
* @var array
*/
private $validExtensions = array();
/**
* The maximum filesize allowed
* @var int
*/
private $maxFileSize = 10485760;
/**
* The error that occured
* @var string
*/
private $error = '';
/**
* @param array $validExtensions a list of valid extensions (like jpeg, xml, bmp, xls...)
* @param int $maxFileSize in bytes (default 10 megabytes)
*/
public function __construct(array $validExtensions = array(), $maxFileSize = 10485760){
$this->validExtensions = $validExtensions;
if((int)$maxFileSize !== $maxFileSize){
throw new Exception('$maxFileSize should be an integer.');
}
$this->maxFileSize = $maxFileSize;
}
/**
* Save the file to the specified path
* @param string $path The path to save the file to
* @return boolean TRUE on success
*/
abstract protected function save($path);
/**
* Get the name of the uploaded file
* @return string
*/
abstract protected function getName();
/**
* Get the size of the uploaded file (bytes)
* @return int
*/
abstract protected function getSize();

/**
* Make sure that the file extension is valid
* @param string $ext The file's extension
*/
private function validateExtension($ext){
//make sure that the file has one of the allowed extensions
if($this->validExtensions && !in_array($ext, $this->validExtensions)){
$these = implode(', ', $this->validExtensions);
if(count($this->validExtensions) > 1){
$this->error = 'File has an invalid extension, it should be one of '. $these.'.';
} else {
$this->error = 'File has an invalid extension, it can only be a(n) '. $these.'.';
}
return FALSE;
}
return TRUE;
}
/**
* Remove invalid characters from the file name (based on what windows says are bad characters to be safe)
* @param string $filename The filename without the extension
* @return string
*/
private function removeBadCharacters($filename){
$seach = array('\\','/',':','*','?','"','<','>','|');
$replace = '_';
return str_replace($search, $replace, $filename);
}
/**
* Handle the uploading of the file
* @param string $uploadDirectory Where the files are
* @param boolean $replaceOldFile Whether or not to replace old files
* @return boolean TRUE on success, FALSE on failure
*/
public function handleUpload($uploadDirectory, $replaceOldFile = FALSE) {
if(!is_string($uploadDirectory)){
throw new Exception('$uploadDir should be a string.');
}
$uploadSize = $this->getSize();
if ($uploadSize == 0) {
$this->error = 'File is empty.';
return FALSE;
}
if ($uploadSize > $this->maxFileSize) {
$this->error = 'File is too large';
return FALSE;
}
$uploaded = $this->getName();
$this->removeBadCharacters($uploaded);
$pathinfo = pathinfo($this->getName());
$filename = $pathinfo['filename'];
$filename = md5(uniqid());
$ext = $pathinfo['extension'];
if(!$this->validateExtension($ext)){
return FALSE;
}
if(!$replaceOldFile){
/// don't overwrite previous files that were uploaded
while (file_exists($uploadDirectory . $filename . '.' . $ext)) {
$filename .= rand(10, 99);
}
}

return $this->save($uploadDirectory . $filename . '.' . $ext);
}
public function getError(){
return $this->error;
}
}

/**
* Handle file uploads via XMLHttpRequest
* @link http://www.w3.org/TR/XMLHttpRequest/
*/
class UploadFileXhr Extends Uploader {
/**
* Save the file to the specified path
* @param string $path
*/
protected function save($path) {
$input = fopen("php://input", "r");
$fp = fopen($path, "w");
if(!$fp){
$this->error = 'Could not save uploaded file.';
return FALSE;
}
while ($data = fread($input, 1024)) {
fwrite($fp, $data);
}
fclose($fp);
fclose($input);
return TRUE;
}
/**
* Get the name of the file
* @return string
*/
protected function getName() {
return $_GET['qqfile'];
}
/**
* Get the size of the file
* @return int
*/
protected function getSize() {
$headers = apache_request_headers();
return (int) $headers['Content-Length'];
}
class UploadedFileXhr {
/**
* Save the file to the specified path
* @return boolean TRUE on success
*/
function save($path) {
$input = fopen("php://input", "r");
$fp = fopen($path, "w");
if(!$fp){
$this->error = 'Could not save uploaded file.';
return FALSE;
}
while ($data = fread($input, 1024)) {
fwrite($fp, $data);
}
fclose($fp);
fclose($input);
return TRUE;
}
function getName() {
return $_GET['qqfile'];
}
function getSize() {
$headers = apache_request_headers();
return (int) $headers['Content-Length'];
}
}

/**
* Handle file uploads via regular form post (uses the $_FILES array)
* @link http://php.net/manual/en/reserved.variables.files.php
*/
class UploadFileForm Extends Uploader {

/**
* Save the file to the specified path
* @param string $path
*/
protected function save($path) {
if(!@move_uploaded_file($_FILES['qqfile']['tmp_name'], $path)){
$this->error = 'Could not save uploaded file.';
return FALSE;
}
return TRUE;
}
/**
* Get the file name
* @return string
*/
protected function getName() {
return $_FILES['qqfile']['name'];
}
/**
* Get the file size in bytes
* @return int
*/
protected function getSize() {
return $_FILES['qqfile']['size'];
}
class UploadedFileForm {
/**
* Save the file to the specified path
* @return boolean TRUE on success
*/
function save($path) {
if(!@move_uploaded_file($_FILES['qqfile']['tmp_name'], $path)){
$this->error = 'Could not save uploaded file.';
return FALSE;
}
return TRUE;
}
function getName() {
return $_FILES['qqfile']['name'];
}
function getSize() {
return $_FILES['qqfile']['size'];
}
}

//send back json headers if you want...
//header('Cache-Control: no-cache, must-revalidate');
//header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
//header('Content-type: application/json');
class FileUploader {
private $allowedExtensions = array();
private $sizeLimit = 10485760;
private $file;

/**
* This is the example that is used for demo.htm
*/
$validTypes = array();
//determine what kind of upload we are getting from the client
if (isset($_GET['qqfile'])) {
$class = 'UploadFileXhr';
} elseif (isset($_FILES['qqfile'])) {
$class = 'UploadFileForm';
} else {
$result = array('success' => FALSE, 'error'=> 'No files were uploaded.');
}
function __construct(array $allowedExtensions = array(), $sizeLimit = 10485760){
$this->validExtensions = $allowedExtensions;
$this->sizeLimit = $sizeLimit;

if(empty($result)){
/**
* @var Uploader
*/
$file = new $class($validTypes);
$result['success'] = $file->handleUpload('uploads/');
//if we failed, get the error message
if(!$result['success']){
$result['error'] = $file->getError();
}
if (isset($_GET['qqfile'])) {
$this->file = new UploadedFileXhr();
} elseif (isset($_FILES['qqfile'])) {
$this->file = new UploadedFileForm();
} else {
$this->file = false;
}
}

/**
* Returns array('success'=>true) or array('error'=>'error message')
*/
function handleUpload($uploadDirectory, $replaceOldFile = FALSE) {
if (!$this->file){
return array('error' => 'No files were uploaded.');
}

$size = $this->file->getSize();

if ($size == 0) {
return array('error' => 'File is empty');
}

if ($size > $this->sizeLimit) {
return array('error' => 'File is too large');
}

$pathinfo = pathinfo($this->file->getName());
$filename = $pathinfo['filename'];
$filename = md5(uniqid());
$ext = $pathinfo['extension'];

if($this->allowedExtensions && !in_array($ext, $this->allowedExtensions)){
$these = implode(', ', $this->validExtensions);
return array('error'=> 'File has an invalid extension, it should be one of '. $these . '.');
}

if(!$replaceOldFile){
/// don't overwrite previous files that were uploaded
while (file_exists($uploadDirectory . $filename . '.' . $ext)) {
$filename .= rand(10, 99);
}
}

if ($this->file->save($uploadDirectory . $filename . '.' . $ext)){
return array('success'=>true);
} else {
return array('error'=> 'Server error. File was not saved.');
}

}
}

// list of valid extensions, ex. array("jpeg", "xml", "bmp")
$allowedExtensions = array();
// max file size in bytes
$sizeLimit = 10485760;

$uploader = new FileUploader();
$result = $uploader->handleUpload('uploads/');
// to pass data through iframe you will need to encode all html tags
echo htmlspecialchars(json_encode($result), ENT_NOQUOTES);
echo htmlspecialchars(json_encode($result), ENT_NOQUOTES);

0 comments on commit e9f2200

Please sign in to comment.