A set of JavaScript tools for working with files.
Download the files from the dist directory, and then:
<div><!-- "js-fileapi-wrapper" -- required class --><divclass="js-fileapi-wrapper upload-btn"><divclass="upload-btn__txt">Choose files</div><inputid="choose" name="files" type="file" multiple/></div><divid="images"><!-- previews --></div></div><script>window.FileAPI={staticPath: '/js/FileAPI/dist/'};</script><scriptsrc="/js/FileAPI/dist/FileAPI.min.js"></script><script>varchoose=document.getElementById('choose');FileAPI.event.on(choose,'change',function(evt){varfiles=FileAPI.getFiles(evt);// Retrieve file listFileAPI.filterFiles(files,function(file,info/**Object*/){if(/^image/.test(file.type)){returninfo.width>=320&&info.height>=240;}returnfalse;},function(files/**Array*/,rejected/**Array*/){if(files.length){// Make preview 100x100FileAPI.each(files,function(file){FileAPI.Image(file).preview(100).get(function(err,img){images.appendChild(img);});});// Uploading FilesFileAPI.upload({url: './ctrl.php',files: {images: files},progress: function(evt){/* ... */},complete: function(err,xhr){/* ... */}});}});});</script>Edit the file crossdomain.xml and place it to the root of the domain to which files will be uploaded.
<script>window.FileAPI={debug: false// debug mode, see Console,cors: false// if used CORS, set `true`,media: false// if used WebCam, set `true`,staticPath: '/js/FileAPI/dist/'// path to '*.swf',postNameConcat: function(name,idx){// Default: object[foo]=1&object[bar][baz]=2// .NET: https://github.com/mailru/FileAPI/issues/121#issuecomment-24590395returnname+(idx!=null ? '['+idx+']' : '');}};</script><scriptsrc="/js/FileAPI/dist/FileAPI.min.js"></script><!-- OR --><script>window.FileAPI={/* options */};require(['FileAPI'],function(FileAPI){// ...});</script>Retrieve file list from input element or event object, also support jQuery.
- input —
HTMLInputElement,changeanddropevent,jQuerycollection orjQuery.Event
varel=document.getElement('my-input');FileAPI.event.on(el,'change',function(evt/**Event*/){// Retrieve file listvarfiles=FileAPI.getFiles(el);// or eventvarfiles=FileAPI.getFiles(evt);});Get info of file (see also: FileAPI.addInfoReader).
- file — file object (https://developer.mozilla.org/en-US/docs/DOM/File)
- callback — function, called after collected info of file
// Get info of image file (FileAPI.exif.js included)FileAPI.getInfo(file,function(err/**String*/,info/**Object*/){if(!err){console.log(info);//{width: 800, height: 600, exif:{..}}}});// Get info of mp3 file (FileAPI.id3.js included)FileAPI.getInfo(file,function(err/**String*/,info/**Object*/){if(!err){console.log(info);//{title: "...", album: "...", artists: "...", ... }}});Filtering the list of files, with additional information about files. See also: FileAPI.getInfo and FileAPI.addInfoReader.
- files — original list of files
- filter — function, takes two arguments:
file— the file itself,info— additional information. - callback — function:
list— files that match the condition,other— all the rest.
// Get list of filevarfiles=FileAPI.getFiles(input);// Filter the ListFileAPI.filterFiles(files,function(file/**Object*/,info/**Object*/){if(/^image/.test(file.type)&&info){returninfo.width>320&&info.height>240;}else{returnfile.size<20*FileAPI.MB;}},function(list/**Array*/,other/**Array*/){if(list.length){// ..}});Get a list of files, including directories.
- evt —
dropevent - callback — function, takes one argument, a list of files
FileAPI.event.on(document,'drop',function(evt/**Event*/){evt.preventDefault();// Get a list of filesFileAPI.getDropFiles(evt,function(files/**Array*/){// ...});});Uploading files to the server (successively). Returns XHR-like object. It is important to remember to correctly worked flash-transport server response body must not be empty, for example, you can pass, just text "ok".
- opts — options object, see Upload options
varel=document.getElementById('my-input');FileAPI.event.on(el,'change',function(evt/**Event*/){varfiles=FileAPI.getFiles(evt);varxhr=FileAPI.upload({url: 'http://rubaxa.org/FileAPI/server/ctrl.php',files: {file: files[0]},complete: function(err,xhr){if(!err){varresult=xhr.responseText;// ...}}});});Adds a handler for the collection of information about a file. See also: FileAPI.getInfo and FileAPI.filterFiles.
- mime — pattern of mime-type
- handler — takes two arguments:
fileobject andcompletefunction callback
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/**Object*/){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'){// ...}});});Reading the contents of the specified File as dataURL.
- file — file object
- callback — function, receives a result
FileAPI.readAsDataURL(file,function(evt/**Object*/){if(evt.type=='load'){// SuccessvardataURL=evt.result;}elseif(evt.type=='progress'){varpr=evt.loaded/evt.total*100;}else{// Error}})Reading the contents of the specified File as BinaryString.
- file — file object
- callback — function, receives a result
FileAPI.readAsBinaryString(file,function(evt/**Object*/){if(evt.type=='load'){// SuccessvarbinaryString=evt.result;}elseif(evt.type=='progress'){varpr=evt.loaded/evt.total*100;}else{// Error}})Reading the contents of the specified File as ArrayBuffer.
- file — file object
- callback — function, receives a result
FileAPI.readAsArrayBuffer(file,function(evt/**Object*/){if(evt.type=='load'){// SuccessvararrayBuffer=evt.result;}elseif(evt.type=='progress'){varpr=evt.loaded/evt.total*100;}else{// Error}})Reading the contents of the specified File as text.
- file — file object
- callback — function, receives a result
FileAPI.readAsText(file,function(evt/**Object*/){if(evt.type=='load'){// Successvartext=evt.result;}elseif(evt.type=='progress'){varpr=evt.loaded/evt.total*100;}else{// Error}})Reading the contents of the specified File as text.
- encoding — a string indicating the encoding to use for the returned data. By default, UTF-8.
FileAPI.readAsText(file,"utf-8",function(evt/**Object*/){if(evt.type=='load'){// Successvartext=evt.result;}elseif(evt.type=='progress'){varpr=evt.loaded/evt.total*100;}else{// Error}})A string containing the URL to which the request is sent.
Additional post data to be sent along with the file uploads.
varxhr=FileAPI.upload({url: '...',data: {'session-id': 123},files: { ... },});Request method, HTML5 only.
varxhr=FileAPI.upload({url: '...',uploadMethod: 'PUT',files: {..},});Pass credentials to upload request, HTML5 only.
varxhr=FileAPI.upload({url: '...',uploadCredentials: false,files: {..},});Additional request headers, HTML5 only.
varxhr=FileAPI.upload({url: '...',headers: {'x-upload': 'fileapi'},files: {..},});Setting to true removes the default timestamp URL parameter.
Key-value object, key — post name, value — File or FileAPI.Image object.
varxhr=FileAPI.upload({url: '...',files: {audio: files}});Chunk size in bytes, HTML5 only.
varxhr=FileAPI.upload({url: '...',files: {images: fileList},chunkSize: 0.5*FileAPI.MB});Number of retries during upload chunks, HTML5 only.
varxhr=FileAPI.upload({url: '...',files: {images: fileList},chunkSize: 0.5*FileAPI.MB,chunkUploadRetry: 3});--
Rules of changes the original image on the client.
varxhr=FileAPI.upload({url: '...',files: {image: imageFiles},// Changes the original imageimageTransform: {// resize by max sidemaxWidth: 800,maxHeight: 600,// Add watermarkoverlay: [{x: 10,y: 10,src: '/i/watemark.png',rel: FileAPI.Image.RIGHT_BOTTOM}]}});--
Rules of image transformation on the client, for more images.
varxhr=FileAPI.upload({url: '...',files: {image: imageFiles},imageTransform: {// resize by max side'huge': {maxWidth: 800,maxHeight: 600},// crop & resize'medium': {width: 320,height: 240,preview: true},// crop & resize + watemark'small': {width: 100,height: 100,// Add watermarkoverlay: [{x: 5,y: 5,src: '/i/watemark.png',rel: FileAPI.Image.RIGHT_BOTTOM}]}}});--
Convert all images to jpeg or png.
varxhr=FileAPI.upload({url: '...',files: {image: imageFiles},imageTransform: {type: 'image/jpeg',quality: 0.86// jpeg quality}});Sent to the server the original image or not, if defined imageTransform option.
--
Auto-rotate images on the basis of EXIF.
--
Prepare options upload for a particular file.
varxhr=FileAPI.upload({url: '...',files: {..}prepare: function(file/**Object*/,options/**Object*/){options.data.secret=utils.getSecretKey(file.name);}});--
Start uploading.
varxhr=FileAPI.upload({url: '...',files: {..}upload: function(xhr/**Object*/,options/**Object*/){// ...}});--
Start file uploading.
varxhr=FileAPI.upload({url: '...',files: {..}fileupload: function(file/**Object*/,xhr/**Object*/,options/**Object*/){// ...}});--
Callback for upload progress events.
varxhr=FileAPI.upload({url: '...',files: {..}progress: function(evt/**Object*/,file/**Object*/,xhr/**Object*/,options/**Object*/){varpr=evt.loaded/evt.total*100;}});--
Callback for upload file progress events.
varxhr=FileAPI.upload({url: '...',files: {..}fileprogress: function(evt/**Object*/,file/**Object*/,xhr/**Object*/,options/**Object*/){varpr=evt.loaded/evt.total*100;}});--
Callback for end upload requests.
varxhr=FileAPI.upload({url: '...',files: {..}complete: function(err/**String*/,xhr/**Object*/,file/**Object/, options/**Object*/){if(!err){// All files successfully uploaded.}}});--
Callback for end upload requests.
varxhr=FileAPI.upload({url: '...',files: {..}filecomplete: function(err/**String*/,xhr/**Object*/,file/**Object/, options/**Object*/){if(!err){// File successfully uploadedvarresult=xhr.responseText;}}});The name of the file referenced by the File object.
The type (MIME type) of the file referenced by the File object.
The size (in bytes) of the file referenced by the File object.
Attach an event handler function.
- el — DOM element
- events — one or more space-separated event types.
- handler — A function to execute when the event is triggered.
Remove an event handler.
- el — DOM element
- events — one or more space-separated event types.
- handler — a handler function previously attached for the event(s).
Attach an event handler function. The handler is executed at most once.
- el — DOM element
- events — one or more space-separated event types.
- handler — a function to execute when the event is triggered.
Attach an drag and drop event handler function.
- el — drop zone
- hover —
dragenteranddragleavelistener - handler —
dropevent handler.
varel=document.getElementById('dropzone');FileAPI.event.dnd(el,function(over){el.style.backgroundColor=over ? '#f60': '';},function(files){if(files.length){// Upload their.}});// or jQuery$('#dropzone').dnd(hoverFn,dropFn);Remove an drag and drop event handler function.
- el — drop zone
- hover —
dragenteranddragleavelistener - handler —
dropevent handler.
// NativeFileAPI.event.dnd.off(el,hoverFn,dropFn);// jQuery$('#dropzone').dndoff(hoverFn,dropFn);--
Class for working with images
The constructor takes a single argument, the File object.
- file — the
Fileobject
FileAPI.Image(imageFile).get(function(err/**String*/,img/**HTMLElement*/){if(!err){document.body.appendChild(img);}});Crop image by width and height.
- width — new image width
- height — new image height
FileAPI.Image(imageFile).crop(640,480).get(function(err/**String*/,img/**HTMLElement*/){});Crop image by x, y, width and height.
- x — offset from the top corner
- y — offset from the left corner
FileAPI.Image(imageFile).crop(100,50,320,240).get(function(err/**String*/,img/**HTMLElement*/){});Resize image.
- width — new image width
- height — new image height
- strategy — enum:
min,max,preview,width,height. By defaultundefined.
FileAPI.Image(imageFile).resize(320,240).get(function(err/**String*/,img/**HTMLElement*/){});// Resize image on by max side.FileAPI.Image(imageFile).resize(320,240,'max').get(function(err/**String*/,img/**HTMLElement*/){});// Resize image on by fixed height.FileAPI.Image(imageFile).resize(240,'height').get(function(err/**String*/,img/**HTMLElement*/){});Crop and resize image.
- width — new image width
- height — new image height
FileAPI.Image(imageFile).preview(100,100).get(function(err/**String*/,img/**HTMLElement*/){});Rotate image.
- deg — rotation angle in degrees
FileAPI.Image(imageFile).rotate(90).get(function(err/**String*/,img/**HTMLElement*/){});Apply filter function. Only HTML5.
- callback — takes two arguments,
canvaselement anddonemethod.
FileAPI.Image(imageFile).filter(function(canvas/**HTMLCanvasElement*/,doneFn/**Function*/){// bla-bla-lbadoneFn();}).get(function(err/**String*/,img/**HTMLElement*/){});Uses CamanJS, include it before FileAPI library.
- name — CamanJS filter name (custom or preset)
Caman.Filter.register("my-funky-filter",function(){// http://camanjs.com/guides/#Extending});FileAPI.Image(imageFile).filter("my-funky-filter")// or .filter("vintage").get(function(err/**String*/,img/**HTMLElement*/){});Add overlay images, eg: watermark.
- images — array of overlays
FileAPI.Image(imageFile).overlay([// Left corner.{x: 10,y: 10,w: 100,h: 10,src: '/i/watermark.png'},// Right bottom corner.{x: 10,y: 10,src: '/i/watermark.png',rel: FileAPI.Image.RIGHT_BOTTOM}]).get(function(err/**String*/,img/**HTMLElement*/){});Get the final image.
- fn — complete callback
To work with a webcam, be sure to set FileAPI.media: true.
Publication of the camera.
- el — target
- options —{
width: 100%,height: 100%,start: true} - callback — the first parameter is a possible error, the second instance of FileAPI.Camera
varel=document.getElementById('cam');FileAPI.Camera.publish(el,{width: 320,height: 240},function(err,cam/**FileAPI.Camera*/){if(!err){// The webcam is ready, you can use it.}});Turn on the camera.
- callback — will be called when the camera ready
varel=document.getElementById('cam');FileAPI.Camera.publish(el,{start: false},function(err,cam/**FileAPI.Camera*/){if(!err){// Turn oncam.start(function(err){if(!err){// The camera is ready for use.}});}});Turn off the camera.
Take a picture with the camera.
varel=document.getElementById('cam');FileAPI.Camera.publish(el,function(err,cam/**FileAPI.Camera*/){if(!err){varshot=cam.shot();// take a picture// create thumbnail 100x100shot.preview(100).get(function(err,img){previews.appendChild(img);});// and/orFileAPI.upload({url: '...',files: {cam: shot});}});1024 bytes
1048576 bytes
1073741824 bytes
1.0995116e+12 bytes
Iterate over an object or array, executing a function for each matched element.
- obj — array or object
- callback — a function to execute for each element.
- thisObject — object to use as
thiswhen executingcallback.
--
Merge the contents of two objects together into the first object.
- dst — an object that will receive the new properties
- src — an object containing additional properties to merge in.
--
Creates a new array with all elements that pass the test implemented by the provided function.
- array — original Array
- callback — Function to test each element of the array.
- thisObject — object to use as
thiswhen executingcallback.
- 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 6+
- crop, resize, preview & rotate (HTML5 or Flash)
- auto orientation by exif (HTML5, if include FileAPI.exif.js or Flash)
HTML5 browser support
This cross-origin resource sharing is used to enable cross-site HTTP requests.
Drag'n'drop events support.
Availability Flash plugin.
Canvas support.
Support dataURI as src for image.
Support chunked upload.
Flash is very "buggy" thing :] The server response can not be empty. Therefore, in the event of a successful uploading http status should be only 200 OK.
Flash settings. It is advisable to place flash on the same server where the files will be uploaded.
<script>varFileAPI={// @default: "./dist/"staticPath: '/js/',// @default: FileAPI.staticPath + "FileAPI.flash.swf"flashUrl: '/statics/FileAPI.flash.swf',// @default: FileAPI.staticPath + "FileAPI.flash.image.swf"flashImageUrl: '/statics/FileAPI.flash.image.swf'};</script><scriptsrc="/js/FileAPI.min.js"></script>Necessarily make this file on the server. Do not forget to replace youdomain.com on the name of your domain.
<?xml version="1.0"?> <!DOCTYPEcross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd"> <cross-domain-policy> <site-controlpermitted-cross-domain-policies="all"/> <allow-access-fromdomain="youdomain.com"secure="false"/> <allow-access-fromdomain="*.youdomain.com"secure="false"/> <allow-http-request-headers-fromdomain="*"headers="*"secure="false"/> </cross-domain-policy>The following sample HTTP POST request is sent from Flash Player to a server-side script if no parameters are specified:
POST /server/ctrl.php HTTP/1.1 Accept: text/* Content-Type: multipart/form-data; boundary=----------Ij5ae0ae0KM7GI3KM7 User-Agent: Shockwave Flash Host: www.youdomain.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 [[..FILE_DATA_HERE..]] ------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7 Content-Disposition: form-data; name="Upload" Submit Query ------------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7--By default FileAPI.flash.swf allows access from any domain via Security.allowDomain("*"). This can lead to same origin bypass vulnerability if swf is loaded from the same domain as your critical data. To prevent this, allow only your domains here and rebuild flash.
<script> (function (ctx, jsonp){'use strict'; var status ={{httpStatus}}, statusText = "{{httpStatusText}}", response = "{{responseBody}}"; try{ctx[jsonp](status, statusText, response)} catch (e){var data = "{\"id\":\""+jsonp+"\",\"status\":"+status+",\"statusText\":\""+statusText+"\",\"response\":\""+response.replace(/\"/g, '\\\\\"')+"\"}"; try{ctx.postMessage(data, document.referrer)} catch (e){} } })(window.parent, '{{request_param_callback}}'); </script> <!-- or --> <?phpinclude'./FileAPI.class.php'; if( strtoupper($_SERVER['REQUEST_METHOD']) == 'POST' ){// Retrieve File List$files = FileAPI::getFiles(); // ... your logic// JSONP callback name$jsonp = isset($_REQUEST['callback']) ? trim($_REQUEST['callback']) : null; // Server response: "HTTP/1.1 200 OK" FileAPI::makeResponse(array( 'status' => FileAPI::OK , 'statusText' => 'OK' , 'body' => array('count' => sizeof($files)) ), $jsonp); exit} ?>Enable CORS.
<?php// Permitted types of requestheader('Access-Control-Allow-Methods: POST, OPTIONS'); // Describe custom headersheader('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Range, Content-Disposition, Content-Type'); // A comma-separated list of domainsheader('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); // Allow cookieheader('Access-Control-Allow-Credentials: true'); if( $_SERVER['REQUEST_METHOD'] == 'OPTIONS' ){exit} if( $_SERVER['REQUEST_METHOD'] == 'POST' ){// ... } ?>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>
Response codes:
- 200 - last chunk is uploaded
- 201 - chunk is successfully saved
- 416 - range is not acceptable error, recoverable
- 500 - server error, recoverable
Simple input[type="file"]
<spanclass="js-fileapi-wrapper" style="position: relative; display: inline-block;"><inputname="files" type="file" multiple/></span>Stylized button.
<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-btninput{top:-10px; right:-40px; z-index:2; position: absolute; cursor: pointer; opacity:0; filter:alpha(opacity=0); font-size:50px} </style><divclass="js-fileapi-wrapper upload-btn"><divclass="upload-btn__txt">Upload files</div><inputname="files" type="file" multiple/></div>Button like link.
<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-linkinput{top:-10px; right:-40px; z-index:2; position: absolute; cursor: pointer; opacity:0; filter:alpha(opacity=0); font-size:50px} </style><aclass="js-fileapi-wrapper upload-link"><spanclass="upload-link__txt">Upload photo</span><inputname="photo" type="file" accept="image/*" /></a>npm install fileapicd fileapinpm installgrunt
- #369: * IEMobile
- #367: * [flash] allow gif and bmp to resize
- #364: * Camera#stop
- #363: * support `Blob` in `FileAPI.getInfo`
- #361: + upload zero-files
- #353: debug mode vs. IE
- #352: correct filename via flash-uploading
- #346, #342, #344: fixes for XSS into Flash-transport
- #322, #308: dnd & safari + $.fn.dnd (store all dropped items)
- #319: NodeJS tesing
- #317, #313: fixed "malformed entry.name (OSX Unicode NFD)"
- #311: fixed "Arithmetic result exceeded 32 bits"
- #289: * WebCam & html5 == false
- #199, #265: flash fix 2015 error with BitmapData
- #177: IE9, IE11 flash.camera remembered settigns
- #254: check 'onLoadFnName' before call
- #272: fixed `entry.createReader().readEntries`
- #253: fixed `proxyXHR.loaded`
- #250: + check `disabled`-attr
- Two new resize strategies `width` and `height`
- #214: iframe transport under IE8
- Fixed iframe-transport (remove `disabled`-attr for input)
- #240: Fixed `FileAPI.event.dnd.off`
- + #228: check callbacks with regexp
- * Updated devDepending
- + #207: support EXIF.Orientation == 4, 5 & 7
- + #176: Add params to the beginning of form
- + #190: Add 204 as a successful response
- + #192: many bugfixes; + `retry` & `multipass` options; + QUnit-tests for BigSizeImage
- + QUnit-tests for iframe-transport
- + `postMessage` for iframe-transport
- + `jsonp: "callback"` option
- * resize: `imageTransform.type` rename to `imageTransform.strategy` (!!!)
- + mailru#165 (#140: fix)
- + test: upload headers
- + test: upload + camanjs
- + test: upload + autoOrientation
- FileAPI.class.php: + HTTP header Content-Type: application/json
- #143: + `FileAPI.flashWebcamUrl` option
- * merge v1.2.7
- + `FileAPI.formData: true` option
- + support 'filter' prop in imageTransform
- + FileAPI.Camera (HTML5 and Flash fallback)
- + jquery.fileapi.js, see demo
- + npm support
- + grunt support
- + requirejs support
- + [#80](https://https://github.com/mailru/FileAPI/issues/80): FileAPI.Image.fn.overlay
- `imageTransform` — now supports: `crop`, `type`, `quality` and `overlay` properties.
- Improved the documentation
- +iOS fix (https://github.com/blueimp/JavaScript-Load-Image)
- [#121](https://github.com/mailru/FileAPI/issues/121): + FileAPI.`postNameConcat:Function(name, idx)`
- [#116](https://github.com/mailru/FileAPI/issues/116): + `cache:false` option for FileAPI.upload
- [#91](https://github.com/mailru/FileAPI/issues/91): replace `new Image` to `FileAPI.newImage`
- + FileAPI.withCredentials: true
- [#90](https://github.com/mailru/FileAPI/issues/90): Fixed `progress` event
- [#105](https://github.com/mailru/FileAPI/issues/105): Fixed `image/jpg` -> `image/jpeg`
- [#108](https://github.com/mailru/FileAPI/issues/108): Check width/height before resize by type(min/max)
- [#86](mailru#86): Smarter upload recovery
- [#87](https://github.com/mailru/FileAPI/issues/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](https://github.com/mailru/FileAPI/issues/82): "undefined" data-fields cause exceptions
- [#83](https://github.com/mailru/FileAPI/issues/83): Allow requests without files
- [#84](mailru#84): Fixed connection abort when waiting for connection recovery
- [#77](mailru#77): Fixed flash.abort(), [#75](https://github.com/mailru/FileAPI/issues/75)
- - `FileAPI.addMime`
- + `FileAPI.accept` — fallback for flash.
- [#67](mailru#67): Added correct httpStatus for upload fail, [#62](mailru#68)
- [#68](mailru#68) Added "Content-Type" for chunked upload, [#65](https://github.com/mailru/FileAPI/pull/65)
- [#69](mailru#69): Fixed network down recovery
- Fixed progress event, [#66](https://github.com/mailru/FileAPI/issues/66)
- Increase flash stage size, [#73](mailru#73)
- - array index from POST-param "name", [#72](https://github.com/mailru/FileAPI/issues/72)
- - dependency on FileAPI.Image for FileAPI.Flash
- [#64](mailru#64): Bufixed for [#63](https://github.com/mailru/FileAPI/issues/63)
- [#57](mailru#57): Chunked file upload
- [#54](https://github.com/mailru/FileAPI/issues/54): added `FileAPI.flashUrl` and `FileAPI.flashImageUrl`
- [#51](https://github.com/mailru/FileAPI/issues/51): remove circular references from `file-objects` (Flash transport)
- added `changelog`
- first release
