simpleUpload.js
A jQuery file upload plugin with a hands-off approach to design.
Download v.1.1
$('#file').simpleUpload("/ajax/upload.php", {
start: function(file){
//upload started
},
progress: function(progress){
//received progress
},
success: function(data){
//upload successful
},
error: function(error){
//upload failed
}
});
Unlike many JavaScript upload libraries on the interwebs, simpleUpload is an extremely simple yet powerful jQuery file upload plugin designed to be non-intrusive, backwards-compatible, flexible, and very easy to understand.
Free to use under the MIT License.
It even works with IE6. I know. I tested them all.
Download simpleUpload.js, minified or unminified, and copy it to your server.
minified – 13KB unminified – 45.7KBsimpleUpload.js is also available via the NPM JavaScript package manager here. Eat your heart out.
npm i jquery-simple-upload
You can either follow the more intricate examples in Example Code, or you can rip off this simple boilerplate. Make sure to change "/js/simpleUpload.min.js"
to the path of simpleUpload on your server, and "/ajax/upload.php"
to the path of your backend script. Note that simpleUpload.js requires jQuery >= 1.7.0.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="/js/simpleUpload.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('input[type=file]').change(function(){
$(this).simpleUpload("/ajax/upload.php", {
start: function(file){
//upload started
console.log("upload started");
},
progress: function(progress){
//received progress
console.log("upload progress: " + Math.round(progress) + "%");
},
success: function(data){
//upload successful
console.log("upload successful!");
console.log(data);
},
error: function(error){
//upload failed
console.log("upload error: " + error.name + ": " + error.message);
}
});
});
});
</script>
</head>
<body>
<input type="file" name="file">
</body>
</html>
Open up your JavaScript console to view the output (CTRL
+SHIFT
+J
for Chrome; CMD
+OPT
+J
on Mac)
In order to keep simpleUpload backwards-compatible, only a few extra steps need to be taken. Depending on whether you are uploading on the same domain name or a different domain, things will differ slightly. These examples are written in PHP, but because no outside scripts or libraries are required, this can be easily converted into any language.
How to upload on the same domain and return data as JSON.
<?php
/*
* All of your application logic with $_FILES["file"] goes here.
* It is important that nothing is outputted yet.
*/
// $output will be converted into JSON
if ($success) {
$output = array("success" => true, "message" => "Success!");
} else {
$output = array("success" => false, "error" => "Failure!");
}
if (($iframeId = (int)$_GET["_iframeUpload"]) > 0) { //old browser...
header("Content-Type: text/html; charset=utf-8");
?>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
var data = {
id: <?php echo $iframeId; ?>,
type: "json",
data: <?php echo json_encode($output); ?>
};
parent.simpleUpload.iframeCallback(data);
</script>
</body>
</html>
<?php
} else { //new browser...
header("Content-Type: application/json; charset=utf-8");
echo json_encode($output);
}
?>
How to upload on a different domain and return data as JSON.
<?php
$remoteOrigin = "http://www.remote-domain.com"; //change to the origin of your webpage
/* FOR AJAX CORS REQUESTS */
if ($_SERVER["HTTP_ORIGIN"]===$remoteOrigin) {
header("Access-Control-Allow-Origin: " . $_SERVER["HTTP_ORIGIN"]);
/* Uncomment to allow cookies across domains */
//header("Access-Control-Allow-Credentials: true");
/* Uncomment to improve performance after testing */
//header("Access-Control-Max-Age: 86400"); // cache for 1 day
}
if ($_SERVER["REQUEST_METHOD"]==="OPTIONS") {
if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"]))
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if (isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"]))
header("Access-Control-Allow-Headers: " . $_SERVER["HTTP_ACCESS_CONTROL_REQUEST_HEADERS"]);
exit(0);
}
/* END AJAX CORS CONFIGURATION */
/*
* All of your application logic with $_FILES["file"] goes here.
* It is important that nothing is outputted yet.
*/
// $output will be converted into JSON
if ($success) {
$output = array("success" => true, "message" => "Success!");
} else {
$output = array("success" => false, "error" => "Failure!");
}
if (($iframeId = (int)$_GET["_iframeUpload"]) > 0) { //old browser...
header("Content-Type: text/html; charset=utf-8");
?>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
var data = {
namespace: "simpleUpload",
id: <?php echo $iframeId; ?>,
type: "json",
data: <?php echo json_encode($output); ?>,
xDomain: "<?php echo $remoteOrigin; ?>"
};
try {
parent.simpleUpload.iframeCallback(data);
} catch(e) {
parent.postMessage(JSON.stringify(data), data.xDomain);
}
</script>
</body>
</html>
<?php
} else { //new browser...
header("Content-Type: application/json; charset=utf-8");
echo json_encode($output);
}
?>
Remember to change $remoteOrigin
at the top to refer to the origin of your frontend webpage. This must include the protocol, host, and any non-standard port number without a trailing slash.
To return data in a format other than JSON, you can do so by specifying the format following type
in the data
object. Note that data of any other type must also be enclosed in quotes. This is because JSON is the only type that seamlessly translates into a JavaScript object; everything else must be returned as a string. So, for example, instead of this:
var data = {
id: <?php echo $iframeId; ?>,
type: "json",
data: <?php echo json_encode($JSON_output); ?>
};
You would write something like this (for XML):
var data = {
id: <?php echo $iframeId; ?>,
type: "xml",
data: "<?php echo addslashes($XML_output); ?>"
};
When not using JSON, it's important to escape quotes so as not to screw up the JavaScript. Inside data
, type
can be any one of five values: "json", "xml", "html", "script", or "text". Choose the one that's appropriate for your data type. Unless you override this value with the expect
option, your data will be outputted either as an object or string, depending on the type
.
Additionally, the Content-Type header towards the bottom of your script (when doing an AJAX upload) should also match your type
. Below is how your code should look for each different data type.
header("Content-Type: application/json; charset=utf-8");
echo json_encode($output);
header("Content-Type: text/xml; charset=utf-8");
echo $output;
header("Content-Type: text/html; charset=utf-8");
echo $output;
header("Content-Type: text/javascript; charset=utf-8");
echo $output;
header("Content-Type: text/plain; charset=utf-8");
echo $output;
Using jQuery, a typical simpleUpload call will look like this:
$(fileInput).simpleUpload(url, options);
fileInput is the file input element (<input type="file">
) or set of elements from which to upload files.
data
option.Usually, you will probably want to upload a file right after it has been selected. To do so, you simply hook up simpleUpload to the onchange event for the file input. You probably also want a progress bar, so this example shows how to do that as well.
$(document).ready(function(){
$('input[type=file]').change(function(){
$(this).simpleUpload("/ajax/upload.php", {
start: function(file){
//upload started
$('#filename').html(file.name);
$('#progress').html("");
$('#progressBar').width(0);
},
progress: function(progress){
//received progress
$('#progress').html("Progress: " + Math.round(progress) + "%");
$('#progressBar').width(progress + "%");
},
success: function(data){
//upload successful
$('#progress').html("Success!<br>Data: " + JSON.stringify(data));
},
error: function(error){
//upload failed
$('#progress').html("Failure!<br>" + error.name + ": " + error.message);
}
});
});
});
(For the sake of the example, CSS styling has been applied and uploads are rejected after 30 seconds by the server)
Multiple files can be selected at once in HTML5-capable browsers. This is useful if you would like to allow users to upload a collection of files versus only 1 file. Using the limit
option, you can also restrict how many files can be uploaded at once.
$(document).ready(function(){
$('input[type=file]').change(function(){
$(this).simpleUpload("/ajax/upload.php?getFormat=1", {
/*
* Each of these callbacks are executed for each file.
* To add callbacks that are executed only once, see init() and finish().
*
* "this" is an object that can carry data between callbacks for each file.
* Data related to the upload is stored in this.upload.
*/
start: function(file){
//upload started
this.block = $('<div class="block"></div>');
this.progressBar = $('<div class="progressBar"></div>');
this.block.append(this.progressBar);
$('#uploads').append(this.block);
},
progress: function(progress){
//received progress
this.progressBar.width(progress + "%");
},
success: function(data){
//upload successful
this.progressBar.remove();
/*
* Just because the success callback is called doesn't mean your
* application logic was successful, so check application success.
*
* Data as returned by the server on...
* success: {"success":true,"format":"..."}
* error: {"success":false,"error":{"code":1,"message":"..."}}
*/
if (data.success) {
//now fill the block with the format of the uploaded file
var format = data.format;
var formatDiv = $('<div class="format"></div>').text(format);
this.block.append(formatDiv);
} else {
//our application returned an error
var error = data.error.message;
var errorDiv = $('<div class="error"></div>').text(error);
this.block.append(errorDiv);
}
},
error: function(error){
//upload failed
this.progressBar.remove();
var error = error.message;
var errorDiv = $('<div class="error"></div>').text(error);
this.block.append(errorDiv);
}
});
});
});
(For the sake of the example, CSS styling has been applied and uploads are rejected after 30 seconds by the server)
Note: While you can select an infinite number of files at once, the maximum number of simultaneous uploads is hard-coded at 10. However, individual browsers also limit the number of simultaneous HTTP connections, often from 2-8. If this limit has been exceeded, the "start" callback is still executed immediately for every file but the actual uploads are silently queued until they can be handled. You can see specific browser limits here.
In this example, we will allow the user to upload multiple files and give them an interface with which they can cancel individual uploads. To cancel an upload inside a callback, it's just a matter of calling this.upload.cancel()
. While we're at it, we will also restrict uploads to either JPEG, GIF, or PNG images with a maximum file size of 5MB.
$(document).ready(function(){
$('input[type=file]').change(function(){
$(this).simpleUpload("/ajax/upload.php?getFormat=1", {
allowedExts: ["jpg", "jpeg", "jpe", "jif", "jfif", "jfi", "png", "gif"],
allowedTypes: ["image/pjpeg", "image/jpeg", "image/png", "image/x-png", "image/gif", "image/x-gif"],
maxFileSize: 5000000, //5MB in bytes
start: function(file){
//upload started
this.block = $('<div class="block"></div>');
this.progressBar = $('<div class="progressBar"></div>');
this.cancelButton = $('<div class="cancelButton">x</div>');
/*
* Since "this" differs depending on the function in which it is called,
* we need to assign "this" to a local variable to be able to access
* this.upload.cancel() inside another function call.
*/
var that = this;
this.cancelButton.click(function(){
that.upload.cancel();
//now, the cancel callback will be called
});
this.block.append(this.progressBar).append(this.cancelButton);
$('#uploads').append(this.block);
},
progress: function(progress){
//received progress
this.progressBar.width(progress + "%");
},
success: function(data){
//upload successful
this.progressBar.remove();
this.cancelButton.remove();
if (data.success) {
//now fill the block with the format of the uploaded file
var format = data.format;
var formatDiv = $('<div class="format"></div>').text(format);
this.block.append(formatDiv);
} else {
//our application returned an error
var error = data.error.message;
var errorDiv = $('<div class="error"></div>').text(error);
this.block.append(errorDiv);
}
},
error: function(error){
//upload failed
this.progressBar.remove();
this.cancelButton.remove();
var error = error.message;
var errorDiv = $('<div class="error"></div>').text(error);
this.block.append(errorDiv);
},
cancel: function(){
//upload cancelled
this.block.fadeOut(400, function(){
$(this).remove();
});
}
});
});
});
(For the sake of the example, CSS styling has been applied and uploads are rejected after 30 seconds by the server)
Assuming your typical simpleUpload call will look like this:
$(fileInput).simpleUpload(url, options);
Either a DOM object or jQuery object referring to a file input element or set of file input elements from which you would like to upload files. For each file input element, a simpleUpload instance is created and all of its options and callbacks refer to that instance. So, given the following HTML:
running:
$('input[type=file]').simpleUpload(url, options);
is the equivalent of running:
$('#file1').simpleUpload(url, options);
$('#file2').simpleUpload(url, options);
$('#file3').simpleUpload(url, options);
Each of these is an upload instance, and all the files from each file selection will be uploaded.
The string URL of the endpoint to which you would like to upload your files. This will most likely be a backend script, for example, /ajax/upload.php
. If uploading to a cloud service, like Amazon S3, this may be something like https://bucket-name.s3.amazonaws.com/
. If you happen to be uploading to Amazon S3, also don't forget to set up CORS and use the data
option to include your key, acl, AWSAccessKeyId, policy, and signature. I don't happen to have a tutorial on how to use simpleUpload with Amazon S3 specifically yet, but the second half of this tutorial might help.
An object containing key-value pairs that can be used to define settings and callbacks for the upload instance.
Some basic settings that can do everything from limiting file uploads, filtering files, setting additional POST data, overriding the file input name, etc. Unlike other libraries that have 118 settings, we have 11. All the ones you'll ever need.
Key | Data Type | Description |
---|---|---|
name | string |
The name of each file sent to the server. If using PHP, this will define the key of the file in the $_FILES array (e.g. $_FILES["name"] ). If name is omitted, the name of the HTML file input element is used. If the element does not have a name, "file" is used.
|
data | object | A set of key-value pairs containing the POST data you would like to send to the server along with each file. This is not automatically populated by any surrounding forms. |
limit | integer | The maximum number of files to accept from a single file input. A value of 0 means no limit. Note that this value is only relevant if multiple-file selections are enabled on the file input using the "multiple" attribute. |
expect | string |
The type of data expected to be received from the server upon a successful upload. Possible values are "auto", "json", "xml", "html", "script", or "text". If omitted, "auto" is the default. If "auto", the type is determined by the Content-Type header of the server's result (e.g. "Content-Type: application/json") if using HTML5. If not using HTML5, it is determined by the type property of the object sent back to the iframeCallback. If type is determined to be "json", an object is returned in the success callback. If type is "xml", an XML object is returned. If "script", the script is executed and returned as a string. If "html" or "text", the data is returned as plain text.
|
allowedExts | array |
An array of acceptable file extensions which a file may have. If a file does not have one of the file extensions listed in the array, the error callback is called with an error type of InvalidFileExtensionError .Note: Using this setting does not guarantee files with an invalid file extension will not be received by your server. You should still do server-side filtering of all input received to ensure your application is secure. |
allowedTypes | array |
An array of acceptable MIME types which a file may have. If a file does not have one of the MIME types listed in the array, the error callback is called with an error type of InvalidFileTypeError . This setting is only used for browsers that support HTML5, since this information is not available for pre-HTML5 browsers.Note: Using this setting does not guarantee files with an invalid MIME type will not be received by your server. You should still do server-side filtering of all input received to ensure your application is secure. |
maxFileSize | integer |
The maximum acceptable size of each file in bytes. If a file is larger than maxFileSize , the error callback is called with an error type of MaxFileSizeError . This setting is only used for browsers that support HTML5, since this information is not available for pre-HTML5 browsers. A value of 0 means no limit.Note: Using this setting does not guarantee files with an invalid size will not be received by your server. You should still do server-side filtering of all input received to ensure your application is secure. |
files | object |
simpleUpload does not handle drag-n-drop directly (I might work on that), but if you manage to grab a files object through another method, such as drag-n-drop, you can pass it directly to simpleUpload using this setting. In that case, you would call simpleUpload like this:$.fn.simpleUpload("upload.php", { files: files }); Naturally, this only works with HTML5 browsers. Attempting this on an older browser will return an error of type UnsupportedError in the error callback:"Your browser does not support this upload method"
|
xhrFields | object |
A set of key-value pairs to set on the native XMLHttpRequest object during an Ajax upload. This could be used to set the withCredentials flag to true , for example, allowing cross-domain cookie access.{ withCredentials: true } Note that this flag will have no effect for older browsers not capable of Ajax file uploads, so I do not recommend relying on getting/setting cookies in your receiving script if it's a cross-domain upload. Instead, I recommend passing cookies over POST using the data setting.
|
forceIframe | boolean |
If set to true , the upload will be performed using the fallback iframe method instead of Ajax. I do not recommend doing this on production systems. It is intended solely for debugging purposes. When first installing and using simpleUpload with your backend script, it is useful to know whether the iframe functionality is working correctly, for older browsers. Setting this to false will use Ajax by default, when available. This is the default value.
|
hashWorker | string |
It has nothing to do with marijuana. It is the URL of the worker script that can be used to generate MD5, SHA-1, or SHA-256 hashes of each file. The generated hash is then sent to the hashComplete callback, where the upload process can be stopped or continued. It is recommended this worker is hosted on the same domain as the calling page, and the path given should be relative to the page.If the worker is hosted on a different domain, it is still possible to reference it, but another javascript file must still be made on the same domain. Inside it, you can just import the remote worker: importScripts("http://remote-domain.com/worker.js"); On your page, hashWorker would then refer to your same-domain script containing the above import.
|
This setting only applies if you have purchased a license to use client-side hashing. More information here. |
Functions that you can set to execute upon certain events. The ones you are most likely to use will probably be start
, progress
, success
, and error
. Also, take note of each callback's context, which defines the value of this
inside the callback.
Key | Description |
---|---|
init |
function(total_uploads) {}
Context: Instance
|
Returned as Paramstotal_uploads : (int) The total number of files that are going to be uploaded.
DescriptionCalled when an upload instance is initialized. It is only called once. Returningfalse in this callback will cancel all uploads for the instance. Returning an integer will define a new limit for the max number of files to upload. All uploads after the new limit will be considered cancelled. However, the cancel callback will not be called.
|
|
start |
function(file) {}
Context: File
|
Returned as Paramsfile : (obj) The file which is going to be uploaded. Included in file is:
DescriptionCalled for each file at the start of each upload. Returningfalse in this callback will cancel the current upload. However, the cancel callback will not be called. The upload process is not actually started until this callback has completed.
|
|
hashComplete |
function(hash, callbacks) {}
Context: File
|
Returned as Paramshash : (string) The calculated hash resulting from the hashWorker .
callbacks : (obj) An object containing callback functions that can continue or stop the upload.These callbacks include:
DescriptionCalled for each file after a hash has been calculated. The upload for this file is essentially halted until one of the callbacks has been called. When combining with a de-duplication system, this is useful because you can check whether a hash exists in your system without even uploading the file. By pausing the upload at this callback, you get the chance to check the file hash and either continue with the upload, if the hash doesn't exist, or finish it as successful, if the hash does exist. If the hash exists but the associated file is not valid for that upload process, you can finish it with an error instead. Each callback will returntrue if the callback executed successfully, and false if not, for example, if another callback was already called or the upload was cancelled elsewhere. Note that if any errors occur while calculating the hash, the default behavior is to proceed with the upload automatically.
Examples on how to use this callback can be found here. |
|
This callback only applies if you have purchased a license to use client-side hashing. More information here. | |
beforeSend |
function(jqXHR, settings) {}
Context: File
|
Returned as ParamsjqXHR : (obj) The jqXHR object to modify before sending the AJAX request.
settings : (obj) The settings object used in the AJAX request.
DescriptionNew in v.1.1. Called right before each AJAX request is made. Virtually identical to jQuery's beforeSend. Use this function to modify the headers of a request, like so:jqXHR.setRequestHeader('x-access-token', token);
Useful when you may want to attach a CSRF token. This function will not be called on older browsers that don't support AJAX file upload. |
|
progress |
function(progress) {}
Context: File
|
Returned as Paramsprogress : (float) The current progress of an upload, from 0-100.
DescriptionCalled for each file when its upload progress has been updated. Note that this callback will not be called during an upload for pre-HTML5 browsers, since client-side upload progress can only be achieved in HTML5 browsers. When an upload is successful, however, this callback will be called with a value of 100 just before thesuccess callback, for older browsers.
|
|
success |
function(data) {}
Context: File
|
Returned as Paramsdata : (varied) The data returned from the server, either as an object or string, as determined by the expect setting.
DescriptionCalled for each file after it has uploaded successfully. For newer browsers, a successful upload is triggered only when the server returns with an HTTP status code of 200 and the outputted data can be parsed in accordance with theexpect setting. In older browsers, the HTTP status code is ignored. A successful upload is only triggered by valid output that can be parsed. Given this, it is recommended that you pass application errors resulting from your backend script through your output instead of using HTTP status codes. In your success callback, you would simply check for those errors upon completion. This will ensure your application is completely backwards-compatible.
New in v.1.1: If you have absolutely no control over the backend or still prefer to use HTTP error codes to indicate application error, you may use the xhr property in the error callback to capture error messages from your server. However, this will not be supported in older browsers.
|
|
error |
function(error) {}
Context: File
|
Returned as Paramserror : (obj) An object containing information related to an error. Properties include:
DescriptionCalled for each file that has encountered an error. A list of possible errors and their types can be found here. For newer browsers, this callback will only be called if the server cannot be reached, an HTTP status code other than 200 was returned, or the output returned by the server could not be parsed in accordance with theexpect setting. In older browsers, this callback will be called only if the server's output cannot be parsed. This is just because of the nature of how uploads are handled in older browsers.
New in v.1.1: The xhr property is useful when the server returns with a non-200 HTTP error code on application error and you need to capture the server's error message. This isn't reliable in older browsers and the xhr property won't exist if there is a different type of error, but if an AJAX request was made and returns with a non-200 HTTP response code, you can expect this property. You should, in general, check for this property's existence before using it.
|
|
cancel |
function() {}
Context: File
|
DescriptionCalled for each file whose upload has been cancelled via theupload.cancel() function in this file's context. This callback is only called if the upload is currently active and has not yet reached success or error . Cancelling an upload inside the init or start callback also does not trigger this callback, unless it is cancelled after the upload has already started, such as through a "click" or "setTimeout" event. If this callback is called, you can be certain success and error will not be called for this file.
|
|
complete |
function(status) {}
Context: File
|
Returned as Paramsstatus : (string) The status of the upload, either "success", "error", or "cancel".
DescriptionCalled for each file after it has completed, regardless of success. This callback will be called immediately after thesuccess , error , and cancel callbacks, regardless of which one was called. However, using the "status" parameter, you can determine the status of the upload. This callback is useful if you want to perform an action after an upload no matter how it ended.
|
|
finish |
function() {}
Context: Instance
|
DescriptionCalled after all file uploads for this instance have completed. It is only called once. This callback may be useful if, for example, you want to re-enable the original file input after it was disabled in theinit callback to prevent more files from being uploaded simultaneously.
|
The context of a callback function is the value of this
within the function. There are only two possible types of contexts within a function, instance
and file
.
Context | Description |
---|---|
instance |
An object that can be used to store data related to the instance and retrieve the file contexts of all the files in the instance. By default, the context contains only one property, "files", a 0-indexed array of all the file contexts.
this = { files: [] }
To generate an array containing the state of each upload after all the uploads have finished, for example, you would run this:
This context is also shared with all callbacks of the same instance that use the same context. So, in other words, you can do the following:
Since this.files is an array of file contexts, see file below.
|
file |
An object that is specific to each file and can be used to store and retrieve data related to that file. By default, it only contains one property, "upload", an object containing data and callbacks related to the upload. Inside this.upload you have the properties:
instance context, you can share data about a file between callbacks that use the file context, which is most callbacks. This allows you to do things like this:
Note: Calling cancel() on an upload does not guarantee the file will not be received by the server. It will simply attempt to stop the upload as soon as possible. After cancel() is called, however, the success and error callbacks will not be called.
|
These are all the possible errors and their types. By looking for these errors in your error
callback, you can substitute these messages for some of your own. The type of error can be accessed using error.name
and its message at error.message
.
Name | Description / Message |
---|---|
InvalidFileExtensionError |
When a file has a file extension other than one of the allowed extensions in the set passed to the allowedExts setting. This can only occur if allowedExts is set.
"That file format is not allowed"
|
InvalidFileTypeError |
When a file has a MIME type other than one of the allowed MIME types in the set passed to the allowedTypes setting. This can only occur if allowedTypes is set.
"That file format is not allowed"
|
MaxFileSizeError |
When a file has a file size larger than the maxFileSize setting. This can only occur if maxFileSize is set.
"That file is too big"
|
HashError |
When you have called the error callback inside the hashComplete callback with a custom error message.
User defined message |
RequestError |
When either the server failed to be reached, an HTTP status code other than 200 was detected upon upload, or the output from the server could not be parsed in accordance with the expect setting.
"Upload failed"
|
UnsupportedError |
When the upload cannot complete because the user's browser does not support the upload method being used. Specifically, if the files setting is set to acquire files from a drag-n-drop operation, for example, this error only occurs if those files cannot be sent over Ajax, which would be required. This is a very rare case, only a possible occurrence in Safari versions 3.1, 3.2, and 4 used by no more than 0.13% of the population.
"Your browser does not support this upload method"
|
InternalError |
When an internal error has occurred. This basically won't happen unless you screw with things like the files object after an upload has started. Leave it alone and you'll be fine.
"There was an error uploading the file"
|
Not sure why you would want to do this. But if you must…it can be done with the following call. You can actually set the maximum number of simultaneous uploads to any number you want. But remember it is still subject to browser limits.
$.fn.simpleUpload.maxSimultaneousUploads(1);
Because simpleUpload was originally developed as part of a personal project of mine having to do with music, I already took the time to find all the possible file extensions and MIME types for several image and audio formats. These may be of use to someone.
$('input[type=file]').simpleUpload("/ajax/upload.php", {
allowedExts: ["jpg", "jpeg", "jpe", "jif", "jfif", "jfi", "png", "gif"],
allowedTypes: ["image/pjpeg", "image/jpeg", "image/png", "image/x-png", "image/gif", "image/x-gif"]
});
$('input[type=file]').simpleUpload("/ajax/upload.php", {
allowedExts: ["mp3", "wav", "wave", "flac", "ogg", "oga", "aac", "mp4", "m4a", "aiff", "aif", "aifc"],
allowedTypes: ["audio/mpeg", "audio/mp3", "audio/x-mpeg", "audio/x-mp3", "audio/mpeg3", "audio/x-mpeg3", "audio/x-mpeg-3", "audio/mpg", "audio/x-mpg", "audio/x-mpegaudio", "audio/mpa", "audio/mpa-robust", "audio/wav", "audio/wave", "audio/x-wav", "audio/x-wave", "audio/x-pn-wav", "audio/vnd.wave", "audio/flac", "audio/x-flac", "audio/ogg", "audio/x-ogg", "application/ogg", "application/x-ogg", "audio/aac", "audio/aacp", "audio/x-aac", "application/octet-stream", "audio/mp4", "audio/m4a", "audio/x-m4a", "audio/mp4a", "audio/mp4a-latm", "audio/mpga", "audio/mpeg4-generic", "audio/x-m4a-lossless", "video/quicktime", "audio/aiff", "audio/x-aiff", "audio/x-aifc", "sound/aiff", "audio/x-pn-aiff"]
});
The default file input element is not the sexiest in the world. Sometimes, you might want to prompt a file selection by clicking on a custom element instead. You can do this using a label, linking to your hidden file input.
(For the sake of the example, CSS styling has been applied)
Although this is supported on most current browsers, some really old browsers will not allow you to assign a label for a file input. If you care to provide full backwards-compatible support, the best solution is to provide a button the user can press in case your custom element isn't working. When the user presses the button, it will then unhide the original file input, which the user can use to upload their file. Or, you can show the original file input in conjunction with your custom UI.