- Multiupload: all browsers that support HTML5 or Flash
- Drag'n'Drop upload: files (HTML5) & directories (Chrome 21+)
- Chunked file upload (HTML5)
- Upload one file: all browsers
- Working with Images: IE6+, FF 3.6+, Chrome 10+, Opera 11.1+, Safari 5.4+
- crop, resize, preview & rotate (HTML5 or Flash)
- auto orientation by exif (HTML5, if include FileAPI.exif.js or Flash)
<spanclass="js-fileapi-wrapper" style="position: relative;"><inputid="user-files" type="file" multiple/></span><divid="preview-list"></div>varinput=document.getElementById('user-files');varpreviewNode=document.getElementById('preview-list');// Drag'n'DropFileAPI.event.dnd(previewNode,function(over){$(this).css('background',over ? 'red' : '');},function(files){// ..});FileAPI.event.on(input,'change',function(evt){varfiles=FileAPI.getFiles(evt.target);// or FileAPI.getFiles(evt)// filteringFileAPI.filterFiles(files,function(file,info){if(/image/.test(file.type)&&info){returninfo.width>=320&&info.height>=240;}else{returnfile.size>128;}},function(fileList,ignor){if(ignor.length){// ...}if(!fileList.length){// empty file listreturn;}// do previewvarimageList=FileAPI.filter(fileList,function(file){return/image/.test(file.type);});FileAPI.each(imageList,function(imageFile){FileAPI.Image(imageFile).preview(100,120).get(function(err,image){if(err){// ...}else{previewNode.appendChild(image);}});});// upload on servervarxhr=FileAPI.upload({url: '...',data: {foo: 'bar'},// POST-data (iframe, flash, html5)headers: {'x-header': '...'},// request headers (html5)files: {files: FileAPI.filter(fileList,function(file){return!/image/.test(file.type);}),pictures: imageList},imageTransform: {maxWidth: 1024,maxHeight: 768},imageAutoOrientation: true,fileprogress: function(evt){// (flash, html5)varpercent=evt.loaded/evt.total*100;// ...},progress: function(evt){// (flash, html5)varpercent=evt.loaded/evt.total*100;// ...},complete: function(err,xhr){// ...}});});});- FileAPI.getFiles(
source:HTMLInput|Event):Array - FileAPI.getDropFiles(
files:Array,callback:Function) - FileAPI.filterFiles(
files:Array,iterator:Function,complete:Function) - FileAPI.upload(
options:Object):XMLHttpRequest - FileAPI.getInfo(
file:File,callback:Function) - FileAPI.readAsImage(
file:File,callback:function) - FileAPI.readAsDataURL(
file:File,callback:function) - FileAPI.readAsBinaryString(
file:File,callback:function) - FileAPI.readAsArrayBuffer(
file:File,callback:function) - FileAPI.readAsText(
file:File,callback:function) - FileAPI.readAsText(
file:File,encoding:String,callback:function)
- FileAPI.event.on(
el:HTMLElement,eventType:String,fn:Function) - FileAPI.event.off(
el:HTMLElement,eventType:String,fn:Function) - FileAPI.event.one(
el:HTMLElement,eventType:String,fn:Function) - FileAPI.event.dnd(
el:HTMLElement,onHover:Function,onDrop:Function) - jQuery('#el').dnd(onHover, onDrop)
- .crop(width[, height])
- .crop(x, y, width[, height])
- .resize(width[, height])
- .resize(width, height,
type:Enum(min,max,preview)) - .preview(width[, height])
- .rotate(deg)
- .get(
fn:Function)
- FileAPI.KB
- FileAPI.MB
- FileAPI.GB
- FileAPI.TB
- FileAPI.support.
html5:Boolean - FileAPI.support.
cors:Boolean - FileAPI.support.
dnd:Boolean - FileAPI.support.
flash:Boolean - FileAPI.support.
canvas:Boolean - FileAPI.support.
dataURI:Boolean - FileAPI.support.
chunked:Boolean - FileAPI.each(
obj:Object|Array,fn:function,context:Mixed) - FileAPI.extend(
dst:Object,src:Object):Object - FileAPI.filter(
list:Array,iterator:Function):Array - FileAPI.isFile(
file:Mixed):Boolean - FileAPI.toBinaryString(
str:Base64):String
FileAPI.event.on('#my-file-1','change',onSelect);// or jQuery$('#my-file-2').on('change',onSelect);functiononSelect(evt/**Event*/){// (1) extract fileList from eventvarfiles=FileAPI.getFiles(evt);// (2) or sovarfiles=FileAPI.getFiles(evt.target);}functiononDrop(evt){FileAPI.getDropFiles(evt,function(files){if(files.length){// ...}});}// ORvarel=document.getElementById('el');FileAPI.event.dnd(el,function(over/**Boolean*/,evt/**Event*/){el.style.background=over ? 'red' : '';},function(files/**Array*/,evt/**Event*/){// ...});FileAPI.getInfo(imageFile/**File*/,function(err/**Boolean*/,info/**Object*/){if(!err){switch(info.exif.Orientation){// ...}}});// ...FileAPI.addInfoReader(/^image/,function(file/**File*/,callback/**Function*/){// http://www.nihilogic.dk/labs/exif/exif.js// http://www.nihilogic.dk/labs/binaryajax/binaryajax.jsFileAPI.readAsBinaryString(file,function(evt){if(evt.type=='load'){varbinaryString=evt.result;varoFile=newBinaryFile(binaryString,0,file.size);varexif=EXIF.readFromBinaryFile(oFile);callback(false,{'exif': exif||{}});}elseif(evt.type=='error'){callback('read_as_binary_string');}elseif(evt.type=='progress'){// ...}});});FileAPI.filterFiles(files,function(file,info){if(/image/.test(file.type)&&info){returninfo.width>320&&info.height>240;}returnfile.size<10*FileAPI.MB;},function(result,ignor){// ...});FileAPI.readAsImage(file,function(evt){if(evt.type=='load'){varimages=document.getElementById('images');images.appendChild(evt.result);}else{// ...}});FileAPI.readAsDataURL(file,function(evt){if(evt.type=='load'){// successvarresult=evt.result;}elseif(evt.type=='progress'){varpr=evt.loaded/evt.total*100;}else{// error}});varxhr=FileAPI.upload({url: '...',data: {foo: 'bar'},headers: {'x-header': '...'},files: {images: FileAPI.filter(files,function(file){return/image/.test(file.type);}),customFile: {file: 'generate.txt',blob: customFileBlob}},chunkSize: 0,// or chunk size in bytes, eg: FileAPI.MB*.5 (html5)chunkUploadRetry: 0,// number of retries during upload chunks (html5)imageTransform: {maxWidth: 1024,maxHeight: 768},imageAutoOrientation: true,prepare: function(file,options){// prepare options for current fileoptions.data.filename=file.name;},upload: function(xhr,options){// start uploading},fileupload: function(xhr,options){// start file uploading},fileprogress: function(evt){// progress file uploadingvarfilePercent=evt.loaded/evt.total*100;},filecomplete: function(err,xhr){if(!err){varresponse=xhr.responseText;}},progress: function(evt){// total progress uploadingvartotalPercent=evt.loaded/evt.total*100;},complete: function(err,xhr){if(!err){// Congratulations, the uploading was successful!}}});- width
:Number - height
:Number - preview
:Boolean - maxWidth
:Number - maxHeight
:Number - rotate
:Number
FileAPI.upload({// ..imageOriginal: false,// don't send original on serverimageTransform: {// (1) Resize to 120x200resize: {width: 120,height: 200}// (2) create preview 320x240thumb: {width: 320,height: 240,preview: true}// (3) Resize by max sidemax: {maxWidth: 800,maxHeight: 600}// (4) Custom resizecustom: function(info,transform){returntransform.crop(100,100,300,200).resize(100,50);}}});// (1) all imagesFileAPI.upload({// ..imageAutoOrientation: true});// (2) or soFileAPI.upload({// ..imageAutoOrientation: true,imageTransform: {width: ..,height: ..}});// (3) or soFileAPI.upload({// ..imageTransform: {rotate: 'auto'}});// (4) only "800x600", original not modifiedFileAPI.upload({// ..imageTransform: {"800x600": {width: 800,height: 600,rotate: 'auto'}}});<script>varFileAPI={// @requiredstaticPath: '/js/'// @default: "./"// @optional,flashUrl: '/js/FileAPI.flash.swf'// @default: FileAPI.staticPath + "FileAPI.flash.swf",flashImageUrl: '/js/FileAPI.flash.image.swf'// @default: FileAPI.staticPath + "FileAPI.flash.image.swf"};</script><scriptsrc="/js/FileAPI.min.js"></script>Flash-request (FileReference)
The following sample HTTP POST request is sent from Flash Player to a server-side script if no parameters are specified:
POST /handler.cfm HTTP/1.1
Accept: text/*
Content-Type: multipart/form-data;
boundary=----------Ij5ae0ae0KM7GI3KM7
User-Agent: Shockwave Flash
Host: www.example.com
Content-Length: 421
Connection: Keep-Alive
Cache-Control: no-cache
------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="Filename"
MyFile.jpg
------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="Filedata"; filename="MyFile.jpg"
Content-Type: application/octet-stream
FileDataHere
------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7
Content-Disposition: form-data; name="Upload"
Submit Query
------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7--
FileAPI.upload({url: '...',files: fileList,chunkSize: .5*FileAPI.MB// 512KB,chunkUploadRetry: 1,complete: function(err,xhr){}});Client and server communicate to each other using the following HTTP headers and status codes.
Client explicitly sets the following headers:
- Content-Range: bytes <start-offset>-<end-offset>/<total>
- Content-Disposition: attachment; filename=<file-name>
Any other headers are set by a target browser and are not used by client. Library does not provide any facilities to track a file uniqueness across requests, it's left on developer's consideration.
Client recognizes the following response codes:
- 200, 201 - chunk is successfully saved
- 416, 500 - recoverable error, library tries to resend chunk 'chunkUploadRetry' times then fails
All the other codes - fatal error, user's involvement is recommend.
File object (https://developer.mozilla.org/en/DOM/File)
{name: 'fileName',type: 'mime-type',size: 'fileSize'}{status: Number,statusText: Number,readyState: Number,response: Blob,responseXML: XML,responseText: String,responseBody: String,getResponseHeader: function(name/**String*/)/**String*/{},getAllResponseHeaders: function()/**Object*/{},abort: function(){}}<?header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Range, Content-Disposition, Content-Type'); // and other custom headersheader('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); // a comma-separated list of domainsheader('Access-Control-Allow-Credentials: true');
if( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ){
exit;
}
if( $_SERVER['REQUEST_METHOD'] == 'POST' ){
// ...
}
?>/controller.php
?foo=bar
&images=...
&callback=...
<script type="text/javascript">
(function (ctx, jsonp){
if( ctx && ctx[jsonp] ){
ctx[jsonp](<?=$statusCode/*200 — OK*/?>, "<?=addslashes($statusText)?>", "<?=addslashes($response)?>");
}
})(this.parent, "<?=htmlspecialchars($_POST['callback'])?>");
</script><spanclass="js-fileapi-wrapper" style="position: relative; display: inline-block;"><inputname="files" type="file" multiple/></span><style>
.upload-btn {
width:130px;
height:25px;
overflow: hidden;
position: relative;
border:3px solid #06c;
border-radius:5px;
background:#0cf;
}
.upload-btn:hover {
background:#09f;
}
.upload-btn__txt {
z-index:1;
position: relative;
color:#fff;
font-size:18px;
font-family:"Helvetica Neue";
line-height:24px;
text-align: center;
text-shadow:01px1px#000;
}
.upload-btn__inp {
top:-10px;
right:-40px;
z-index:2;
position: absolute;
cursor: pointer;
opacity:0;
filter:alpha(opacity=0);
font-size:50px;
}
</style><divclass="upload-btn js-fileapi-wrapper"><divclass="upload-btn__txt">Upload files</div><inputclass="upload-btn__inp" name="files" type="file" multiple/></div><style>
.upload-link {
color:#36c;
display: inline-block;
*zoom:1;
*display: inline;
overflow: hidden;
position: relative;
padding-bottom:2px;
text-decoration: none;
}
.upload-link__txt {
z-index:1;
position: relative;
border-bottom:1px dotted #36c;
}
.upload-link:hover .upload-link__txt {
color:#f00;
border-bottom-color:#f00;
}
.upload-link__inp {
top:-10px;
right:-40px;
z-index:2;
position: absolute;
cursor: pointer;
opacity:0;
filter:alpha(opacity=0);
font-size:50px;
}
</style><aclass="upload-link js-fileapi-wrapper"><spanclass="upload-link__txt">Upload photo</span><inputclass="upload-link__inp" name="photo" type="file" accept=".jpg,.jpeg,.gif" /></a>- FileAPI.withCredentials: true
- #90: Fixed
progressevent
- #86: Smarter upload recovery
- #87: Fixed upload files into browsers that do not support FormData
- Fixed support "accept" attribute for Flash.
- Fixed detection of HTML5 support for FireFox 3.6
- FileAPI.html5 option, default "true"
- Fixed auto orientation image by EXIF (Flash)
- Fixed image dimensions after rotate (Flash)
- #82: "undefined" data-fields cause exceptions
- #83: Allow requests without files
- #84: Fixed connection abort when waiting for connection recovery
- #67: Added correct httpStatus for upload fail, #62
- #68 Added "Content-Type" for chunked upload, #65
- #69: Fixed network down recovery
- Fixed progress event, #66
- Increase flash stage size, #73
- array index from POST-param "name", #72
- dependency on FileAPI.Image for FileAPI.Flash
- #57: Chunked file upload
- #54: added
FileAPI.flashUrlandFileAPI.flashImageUrl
- #51: remove circular references from
file-objects(Flash transport) - added
changelog
- first release