Compare commits

..

7 Commits

Author SHA1 Message Date
Paulo
45e1812d0d Updating Angular Version to 6 2018-05-23 16:23:19 -03:00
Paulo
04eef8895e Updating Naming and Files to Work With Services 2018-05-23 12:35:49 -03:00
Paulo
8ae876445e Improving ReadME 2018-03-09 10:22:26 -03:00
Paulo
5a84b9eb0c Fixing Issues with file upload and adding more Helper classes! 2018-03-09 10:07:00 -03:00
Paulo
6c76a590eb Improving the Chunk Method 2018-02-23 13:03:05 -03:00
Paulo
4ead005a66 Fixing README 2018-02-09 22:48:17 -02:00
Paulo
9e8aec3e4a Adding Support For Chunk File Upload
Changes to implement chunk file upload, more information on the README
2018-02-09 22:45:20 -02:00
32 changed files with 11607 additions and 9362 deletions

View File

@@ -1,57 +0,0 @@
{
"project": {
"name": "ng2-file-upload"
},
"apps": [
{
"root": "demo/src",
"outDir": "demo/dist",
"assets": [
"assets"
],
"index": "index.html",
"main": "main.ts",
"test": "../../scripts/test.ts",
"tsconfig": "tsconfig.json",
"prefix": "",
"mobile": false,
"styles": [
],
"scripts": [
],
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
}
],
"addons": [],
"packages": [],
"e2e": {
"protractor": {
"config": "protractor.conf.js"
}
},
"test": {
"karma": {
"config": "karma.conf.js"
}
},
"defaults": {
"styleExt": "css",
"prefixInterfaces": false,
"inline": {
"style": false,
"template": false
},
"spec": {
"class": false,
"component": true,
"directive": true,
"module": false,
"pipe": true,
"service": true
}
}
}

View File

@@ -1,11 +0,0 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

View File

@@ -1,13 +1,11 @@
language: node_js language: node_js
node_js: node_js:
- "10.15.0" - "6"
sudo: required
services:
- xvfb
before_install: before_install:
- google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost & - export CHROME_BIN=chromium-browser
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
script: script:
- npm run pretest - npm run pretest
@@ -17,7 +15,6 @@ after_success:
- ./node_modules/.bin/codecov - ./node_modules/.bin/codecov
addons: addons:
chrome: stable
firefox: "latest" firefox: "latest"
apt: apt:
sources: sources:

View File

@@ -1,108 +1,108 @@
<a name="1.3.0"></a> <a name="1.3.0"></a>
# [1.3.0](https://github.com/valor-software/ng2-file-upload/compare/v1.2.0...v1.3.0) (2017-11-25) # [1.3.0](https://github.com/valor-software/ng2-chunk-file-upload/compare/v1.2.0...v1.3.0) (2017-11-25)
### Features ### Features
* **file-upload:** Add response and function to modify the request body ([#901](https://github.com/valor-software/ng2-file-upload/pull/901)) * **file-upload:** Add response and function to modify the request body ([#901](https://github.com/valor-software/ng2-chunk-file-upload/pull/901))
* **file-upload** add file type .zip ([#911](https://github.com/valor-software/ng2-file-upload/pull/911)) * **file-upload** add file type .zip ([#911](https://github.com/valor-software/ng2-chunk-file-upload/pull/911))
### Bug Fixes ### Bug Fixes
* **file-uploader** Update: setOptions ([#904](https://github.com/valor-software/ng2-file-upload/pull/904)) * **file-uploader** Update: setOptions ([#904](https://github.com/valor-software/ng2-chunk-file-upload/pull/904))
* **docs** Fix correct path for isHTML5 option ([#844](https://github.com/valor-software/ng2-file-upload/pull/844)) * **docs** Fix correct path for isHTML5 option ([#844](https://github.com/valor-software/ng2-chunk-file-upload/pull/844))
* **docs** Added onFileDrop() event to documentation ([#857](https://github.com/valor-software/ng2-file-upload/pull/857)) * **docs** Added onFileDrop() event to documentation ([#857](https://github.com/valor-software/ng2-chunk-file-upload/pull/857))
<a name="1.2.1"></a> <a name="1.2.1"></a>
## [1.2.1](https://github.com/valor-software/ng2-file-upload/compare/v1.2.0...v1.2.1) (2017-04-10) ## [1.2.1](https://github.com/valor-software/ng2-chunk-file-upload/compare/v1.2.0...v1.2.1) (2017-04-10)
### Features ### Features
* **package:** relaxed peer dependencies to allow ng v4 ([#713](https://github.com/valor-software/ng2-file-upload/issues/713)) ([7704e0e](https://github.com/valor-software/ng2-file-upload/commit/7704e0e)) * **package:** relaxed peer dependencies to allow ng v4 ([#713](https://github.com/valor-software/ng2-chunk-file-upload/issues/713)) ([7704e0e](https://github.com/valor-software/ng2-chunk-file-upload/commit/7704e0e))
<a name="1.2.0"></a> <a name="1.2.0"></a>
# [1.2.0](https://github.com/valor-software/ng2-file-upload/compare/v1.1.3-0...v1.2.0) (2017-01-17) # [1.2.0](https://github.com/valor-software/ng2-chunk-file-upload/compare/v1.1.3-0...v1.2.0) (2017-01-17)
### Bug Fixes ### Bug Fixes
* **headers:** Add FileItem headers to XHR ([#553](https://github.com/valor-software/ng2-file-upload/issues/553)) ([e4a7099](https://github.com/valor-software/ng2-file-upload/commit/e4a7099)), closes [#552](https://github.com/valor-software/ng2-file-upload/issues/552) * **headers:** Add FileItem headers to XHR ([#553](https://github.com/valor-software/ng2-chunk-file-upload/issues/553)) ([e4a7099](https://github.com/valor-software/ng2-chunk-file-upload/commit/e4a7099)), closes [#552](https://github.com/valor-software/ng2-chunk-file-upload/issues/552)
### Features ### Features
* **file-select:** Clear file select automatically ([#524](https://github.com/valor-software/ng2-file-upload/issues/524)) ([410efda](https://github.com/valor-software/ng2-file-upload/commit/410efda)) * **file-select:** Clear file select automatically ([#524](https://github.com/valor-software/ng2-chunk-file-upload/issues/524)) ([410efda](https://github.com/valor-software/ng2-chunk-file-upload/commit/410efda))
* **fileUpload:** added additionalParameter ([#565](https://github.com/valor-software/ng2-file-upload/issues/565)) ([397de09](https://github.com/valor-software/ng2-file-upload/commit/397de09)) * **fileUpload:** added additionalParameter ([#565](https://github.com/valor-software/ng2-chunk-file-upload/issues/565)) ([397de09](https://github.com/valor-software/ng2-chunk-file-upload/commit/397de09))
* **package:** upgrade to ng v2.3+ ([#574](https://github.com/valor-software/ng2-file-upload/issues/574)) ([3cc6a99](https://github.com/valor-software/ng2-file-upload/commit/3cc6a99)) * **package:** upgrade to ng v2.3+ ([#574](https://github.com/valor-software/ng2-chunk-file-upload/issues/574)) ([3cc6a99](https://github.com/valor-software/ng2-chunk-file-upload/commit/3cc6a99))
<a name="1.1.3-0"></a> <a name="1.1.3-0"></a>
## [1.1.3-0](https://github.com/valor-software/ng2-file-upload/compare/v1.1.2...v1.1.3-0) (2016-10-19) ## [1.1.3-0](https://github.com/valor-software/ng2-chunk-file-upload/compare/v1.1.2...v1.1.3-0) (2016-10-19)
### Bug Fixes ### Bug Fixes
* **typing:** added authTokenHeader property to options and file upload class ([b55c852](https://github.com/valor-software/ng2-file-upload/commit/b55c852)) * **typing:** added authTokenHeader property to options and file upload class ([b55c852](https://github.com/valor-software/ng2-chunk-file-upload/commit/b55c852))
### Features ### Features
* **build:** added support for AoT and ng-cli ([f0b2879](https://github.com/valor-software/ng2-file-upload/commit/f0b2879)), closes [#436](https://github.com/valor-software/ng2-file-upload/issues/436) * **build:** added support for AoT and ng-cli ([f0b2879](https://github.com/valor-software/ng2-chunk-file-upload/commit/f0b2879)), closes [#436](https://github.com/valor-software/ng2-chunk-file-upload/issues/436)
* **file-upload:** Add the possibility of set the token header ([#213](https://github.com/valor-software/ng2-file-upload/issues/213)) ([282295c](https://github.com/valor-software/ng2-file-upload/commit/282295c)) * **file-upload:** Add the possibility of set the token header ([#213](https://github.com/valor-software/ng2-chunk-file-upload/issues/213)) ([282295c](https://github.com/valor-software/ng2-chunk-file-upload/commit/282295c))
<a name="1.1.2"></a> <a name="1.1.2"></a>
## [1.1.2](https://github.com/valor-software/ng2-file-upload/compare/v1.1.1...v1.1.2) (2016-10-17) ## [1.1.2](https://github.com/valor-software/ng2-chunk-file-upload/compare/v1.1.1...v1.1.2) (2016-10-17)
### Features ### Features
* **package:** allow of ng2 v2.0.* and v2.*.* ([87395e6](https://github.com/valor-software/ng2-file-upload/commit/87395e6)) * **package:** allow of ng2 v2.0.* and v2.*.* ([87395e6](https://github.com/valor-software/ng2-chunk-file-upload/commit/87395e6))
<a name="1.1.1"></a> <a name="1.1.1"></a>
## [1.1.1](https://github.com/valor-software/ng2-file-upload/compare/v1.0.3...v1.1.1) (2016-10-17) ## [1.1.1](https://github.com/valor-software/ng2-chunk-file-upload/compare/v1.0.3...v1.1.1) (2016-10-17)
### Bug Fixes ### Bug Fixes
* **uploader:** Add the ability to upload files via PUT instead of POST ([#239](https://github.com/valor-software/ng2-file-upload/issues/239)) ([e068511](https://github.com/valor-software/ng2-file-upload/commit/e068511)) * **uploader:** Add the ability to upload files via PUT instead of POST ([#239](https://github.com/valor-software/ng2-chunk-file-upload/issues/239)) ([e068511](https://github.com/valor-software/ng2-chunk-file-upload/commit/e068511))
* **zone.js:** error in Safari, Added Typings ([#221](https://github.com/valor-software/ng2-file-upload/issues/221)) ([db77e89](https://github.com/valor-software/ng2-file-upload/commit/db77e89)) * **zone.js:** error in Safari, Added Typings ([#221](https://github.com/valor-software/ng2-chunk-file-upload/issues/221)) ([db77e89](https://github.com/valor-software/ng2-chunk-file-upload/commit/db77e89))
### Features ### Features
* **multipart:** Create disableMultipart option in FileUploader ([#224](https://github.com/valor-software/ng2-file-upload/issues/224)) ([22307d2](https://github.com/valor-software/ng2-file-upload/commit/22307d2)) * **multipart:** Create disableMultipart option in FileUploader ([#224](https://github.com/valor-software/ng2-chunk-file-upload/issues/224)) ([22307d2](https://github.com/valor-software/ng2-chunk-file-upload/commit/22307d2))
* **package:** angular ~2.0.1 stable release ([#425](https://github.com/valor-software/ng2-file-upload/issues/425)) ([3fec385](https://github.com/valor-software/ng2-file-upload/commit/3fec385)) * **package:** angular ~2.0.1 stable release ([#425](https://github.com/valor-software/ng2-chunk-file-upload/issues/425)) ([3fec385](https://github.com/valor-software/ng2-chunk-file-upload/commit/3fec385))
* **package:** updated to typescript 2 ([4fef496](https://github.com/valor-software/ng2-file-upload/commit/4fef496)) * **package:** updated to typescript 2 ([4fef496](https://github.com/valor-software/ng2-chunk-file-upload/commit/4fef496))
<a name="1.1.0"></a> <a name="1.1.0"></a>
# [1.1.0](https://github.com/valor-software/ng2-file-upload/compare/v1.0.3...v1.1.0) (2016-09-21) # [1.1.0](https://github.com/valor-software/ng2-chunk-file-upload/compare/v1.0.3...v1.1.0) (2016-09-21)
### Bug Fixes ### Bug Fixes
* **uploader:** Add the ability to upload files via PUT instead of POST ([#239](https://github.com/valor-software/ng2-file-upload/issues/239)) ([e068511](https://github.com/valor-software/ng2-file-upload/commit/e068511)) * **uploader:** Add the ability to upload files via PUT instead of POST ([#239](https://github.com/valor-software/ng2-chunk-file-upload/issues/239)) ([e068511](https://github.com/valor-software/ng2-chunk-file-upload/commit/e068511))
* **zone.js:** error in Safari, Added Typings ([#221](https://github.com/valor-software/ng2-file-upload/issues/221)) ([db77e89](https://github.com/valor-software/ng2-file-upload/commit/db77e89)) * **zone.js:** error in Safari, Added Typings ([#221](https://github.com/valor-software/ng2-chunk-file-upload/issues/221)) ([db77e89](https://github.com/valor-software/ng2-chunk-file-upload/commit/db77e89))
### Features ### Features
* **multipart:** Create disableMultipart option in FileUploader ([#224](https://github.com/valor-software/ng2-file-upload/issues/224)) ([22307d2](https://github.com/valor-software/ng2-file-upload/commit/22307d2)) * **multipart:** Create disableMultipart option in FileUploader ([#224](https://github.com/valor-software/ng2-chunk-file-upload/issues/224)) ([22307d2](https://github.com/valor-software/ng2-chunk-file-upload/commit/22307d2))
* **package:** updated to typescript 2 ([4fef496](https://github.com/valor-software/ng2-file-upload/commit/4fef496)) * **package:** updated to typescript 2 ([4fef496](https://github.com/valor-software/ng2-chunk-file-upload/commit/4fef496))
<a name="1.0.3"></a> <a name="1.0.3"></a>
## [1.0.3](https://github.com/valor-software/ng2-file-upload/compare/v1.0.2...v1.0.3) (2016-05-12) ## [1.0.3](https://github.com/valor-software/ng2-chunk-file-upload/compare/v1.0.2...v1.0.3) (2016-05-12)
@@ -112,17 +112,17 @@
### Bug Fixes ### Bug Fixes
* **upload:** merge fix and get filters fix ([ef6091c](https://github.com/valor-software/ng2-file-upload/commit/ef6091c)) * **upload:** merge fix and get filters fix ([ef6091c](https://github.com/valor-software/ng2-chunk-file-upload/commit/ef6091c))
### Chores ### Chores
* **build:** ng2 style guide applied ([aee69d8](https://github.com/valor-software/ng2-file-upload/commit/aee69d8)) * **build:** ng2 style guide applied ([aee69d8](https://github.com/valor-software/ng2-chunk-file-upload/commit/aee69d8))
### Features ### Features
* **package:** upgrade to angular 2.0.0-rc.1 ([#176](https://github.com/valor-software/ng2-file-upload/issues/176)) ([13c5c35](https://github.com/valor-software/ng2-file-upload/commit/13c5c35)), closes [#180](https://github.com/valor-software/ng2-file-upload/issues/180) * **package:** upgrade to angular 2.0.0-rc.1 ([#176](https://github.com/valor-software/ng2-chunk-file-upload/issues/176)) ([13c5c35](https://github.com/valor-software/ng2-chunk-file-upload/commit/13c5c35)), closes [#180](https://github.com/valor-software/ng2-chunk-file-upload/issues/180)
### BREAKING CHANGES ### BREAKING CHANGES

106
README.md
View File

@@ -1,31 +1,31 @@
# ng2-file-upload [![npm version](https://badge.fury.io/js/ng2-file-upload.svg)](http://badge.fury.io/js/ng2-file-upload) [![npm downloads](https://img.shields.io/npm/dm/ng2-file-upload.svg)](https://npmjs.org/ng2-file-upload)[![slack](https://ngx-slack.herokuapp.com/badge.svg)](https://ngx-slack.herokuapp.com) # ng2-chunk-file-upload [![npm version](https://badge.fury.io/js/ng2-chunk-file-upload.svg)](http://badge.fury.io/js/ng2-chunk-file-upload) [![npm downloads](https://img.shields.io/npm/dm/ng2-chunk-file-upload.svg)](https://npmjs.org/ng2-chunk-file-upload)[![slack](https://ngx-slack.herokuapp.com/badge.svg)](https://ngx-slack.herokuapp.com)
Easy to use Angular2 directives for files upload ([demo](http://valor-software.github.io/ng2-file-upload/)) Easy to use Angular2 directives for files upload ([demo](http://valor-software.github.io/ng2-chunk-file-upload/))
[![Angular 2 Style Guide](https://mgechev.github.io/angular2-style-guide/images/badge.svg)](https://github.com/mgechev/angular2-style-guide) [![Angular 2 Style Guide](https://mgechev.github.io/angular2-style-guide/images/badge.svg)](https://github.com/mgechev/angular2-style-guide)
[![Build Status](https://travis-ci.org/valor-software/ng2-file-upload.svg?branch=development)](https://travis-ci.org/valor-software/ng2-file-upload) [![Build Status](https://travis-ci.org/valor-software/ng2-chunk-file-upload.svg?branch=development)](https://travis-ci.org/valor-software/ng2-chunk-file-upload)
[![Dependency Status](https://david-dm.org/valor-software/ng2-file-upload.svg)](https://david-dm.org/valor-software/ng2-file-upload) [![Dependency Status](https://david-dm.org/valor-software/ng2-chunk-file-upload.svg)](https://david-dm.org/valor-software/ng2-chunk-file-upload)
## Quick start ## Quick start
1. A recommended way to install ***ng2-file-upload*** is through [npm](https://www.npmjs.com/search?q=ng2-file-upload) package manager using the following command: 1. A recommended way to install ***ng2-chunk-file-upload*** is through [npm](https://www.npmjs.com/search?q=ng2-chunk-file-upload) package manager using the following command:
`npm i ng2-file-upload --save` `npm i ng2-chunk-file-upload --save`
Alternatively, you can [download it in a ZIP file](https://github.com/valor-software/ng2-file-upload/archive/master.zip). Alternatively, you can [download it in a ZIP file](https://github.com/valor-software/ng2-chunk-file-upload/archive/master.zip).
2. Currently `ng2-file-upload` contains two directives: `ng2-file-select` and `ng2-file-drop`. `ng2-file-select` is used for 'file-input' field of form and 2. Currently `ng2-chunk-file-upload` contains two directives: `ng2-file-select` and `ng2-file-drop`. `ng2-file-select` is used for 'file-input' field of form and
`ng2-file-drop` is used for area that will be used for dropping of file or files. `ng2-file-drop` is used for area that will be used for dropping of file or files.
3. More information regarding using of ***ng2-file-upload*** is located in 3. More information regarding using of ***ng2-chunk-file-upload*** is located in
[demo](http://valor-software.github.io/ng2-file-upload/) and [demo sources](https://github.com/valor-software/ng2-file-upload/tree/master/demo). [demo](http://valor-software.github.io/ng2-chunk-file-upload/) and [demo sources](https://github.com/valor-software/ng2-chunk-file-upload/tree/master/demo).
## Using ***ng2-file-upload*** in a project ## Using ***ng2-chunk-file-upload*** in a project
1. Install as shown in the above section. 1. Install as shown in the above section.
2. Import `FileUploadModule` into the module that declares the component using ***ng2-file-upload***: 2. Import `FileUploadModule` into the module that declares the component using ***ng2-chunk-file-upload***:
```import { FileUploadModule } from 'ng2-file-upload';``` ```import { FileUploadModule } from 'ng2-chunk-file-upload';```
3. Add it to `[imports]` under `@NgModule`: 3. Add it to `[imports]` under `@NgModule`:
@@ -33,7 +33,7 @@ Easy to use Angular2 directives for files upload ([demo](http://valor-software.g
4. Import `FileUploader` into the component: 4. Import `FileUploader` into the component:
```import { FileUploader } from 'ng2-file-upload';``` ```import { FileUploader } from 'ng2-chunk-file-upload';```
5. Create a variable for the API url: 5. Create a variable for the API url:
@@ -47,7 +47,7 @@ Easy to use Angular2 directives for files upload ([demo](http://valor-software.g
### Properties ### Properties
- `uploader` - (`FileUploader`) - uploader object. See using in [demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.ts) - `uploader` - (`FileUploader`) - uploader object. See using in [demo](https://github.com/valor-software/ng2-chunk-file-upload/blob/master/demo/components/file-upload/simple-demo.ts)
### Events ### Events
- `onFileSelected` - fires when files are selected and added to the uploader queue - `onFileSelected` - fires when files are selected and added to the uploader queue
@@ -56,7 +56,7 @@ Easy to use Angular2 directives for files upload ([demo](http://valor-software.g
### Properties ### Properties
- `uploader` - (`FileUploader`) - uploader object. See using in [demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.ts) - `uploader` - (`FileUploader`) - uploader object. See using in [demo](https://github.com/valor-software/ng2-chunk-file-upload/blob/master/demo/components/file-upload/simple-demo.ts)
Parameters supported by this object: Parameters supported by this object:
@@ -67,23 +67,89 @@ Easy to use Angular2 directives for files upload ([demo](http://valor-software.g
5. `formatDataFunction` - Function to modify the request body. 'DisableMultipart' must be 'true' for this function to be called. 5. `formatDataFunction` - Function to modify the request body. 'DisableMultipart' must be 'true' for this function to be called.
6. `formatDataFunctionIsAsync` - Informs if the function sent in 'formatDataFunction' is asynchronous. Defaults to false. 6. `formatDataFunctionIsAsync` - Informs if the function sent in 'formatDataFunction' is asynchronous. Defaults to false.
7. `parametersBeforeFiles` - States if additional parameters should be appended before or after the file. Defaults to false. 7. `parametersBeforeFiles` - States if additional parameters should be appended before or after the file. Defaults to false.
8. `chunkSize` - The Size of each chunk in Bytes, if this parameter is set the file chunk upload functionality will run. Defaults to Null.
9. `currentChunkParam` - Parameter Sent with the chunk request, the current chunk number of the file. Defaults to 'current_chunk'.
10. `totalChunkParam` - Parameter Sent with the chunk request, the total number of chunks of the file. Defaults to 'total_chunks'.
11. `chunkMethod` - After the first chunk, this method is set. Defaults to 'PUT' because is the standard for update.
### Events ### Events
- `fileOver` - it fires during 'over' and 'out' events for Drop Area; returns `boolean`: `true` if file is over Drop Area, `false` in case of out. - `fileOver` - it fires during 'over' and 'out' events for Drop Area; returns `boolean`: `true` if file is over Drop Area, `false` in case of out.
See using in [ts demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.ts) and See using in [ts demo](https://github.com/valor-software/ng2-chunk-file-upload/blob/master/demo/components/file-upload/simple-demo.ts) and
[html demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.html) [html demo](https://github.com/valor-software/ng2-chunk-file-upload/blob/master/demo/components/file-upload/simple-demo.html)
- `onFileDrop` - it fires after a file has been dropped on a Drop Area; you can pass in `$event` to get the list of files that were dropped. i.e. `(onFileDrop)="dropped($event)"` - `onFileDrop` - it fires after a file has been dropped on a Drop Area; you can pass in `$event` to get the list of files that were dropped. i.e. `(onFileDrop)="dropped($event)"`
# Troubleshooting # Troubleshooting
Please follow this guidelines when reporting bugs and feature requests: Please follow this guidelines when reporting bugs and feature requests:
1. Use [GitHub Issues](https://github.com/valor-software/ng2-file-upload/issues) board to report bugs and feature requests (not our email address) 1. Use [GitHub Issues](https://github.com/valor-software/ng2-chunk-file-upload/issues) board to report bugs and feature requests (not our email address)
2. Please **always** write steps to reproduce the error. That way we can focus on fixing the bug, not scratching our heads trying to reproduce it. 2. Please **always** write steps to reproduce the error. That way we can focus on fixing the bug, not scratching our heads trying to reproduce it.
Thanks for understanding! Thanks for understanding!
## Using/Sending Chunk Files Feature
If you want to send the files chunked you can just set the chunk paramets on the uploader object
If your chunk request changes the link after the first request you should use this code
```typescript
this.uploader.onCompleteChunk = (item,response,status,headers)=>{
response = JSON.parse(response);
if(response['id']){
item.url = YOUR_NEW_URL+response['id']+'/';
}
}
```
### Code snippet on how to use the Chunk File Feature on your code
```typescript
...
import { FileUploader } from 'ng2-chunk-file-upload';
...
export class SimpleDemoComponent {
...
uploader:FileUploader;
...
constructor () {
...
this.uploader = new FileUploader({
url: URL,
disableMultipart : false,
isHTML5: true,
chunkSize: (1024*1024), // 2MB
currentChunkParam: 'current_chunk',
totalChunkParam: 'total_chunks',
chunkMethod: 'PUT',
//authToken = 'JWT '+TOKEN,
});
this.uploader.onBeforeUploadItem = (item) => {
// If you use credentials this might help you with the "Access-Control-Allow-Origin" error
item.withCredentials = false;
};
this.uploader.onCompleteChunk = (item, response, status, headers) => {
//Insert the Logic here to start uploading next chunks
// Example, setting the ID of the File uploaded and chaning the link for the next request
// In my Case the API is using a put method with the link containing the PK of the object
response = JSON.parse(response);
if (response['id']) {
item.setId(response['id']);
item.url = this.media_url + item.getId() + '/';
}
};
this.uploader.onErrorItem = (item, response, status, headers) => {
// Treat the error on the upload
// On the chunk method we try to upload a chunk for 10 times before triggering this error
};
this.uploader.onRemoveItem = (item) => {
// Treat the file removal from the server
};
...
}
```
### License ### License
The MIT License (see the [LICENSE](https://github.com/valor-software/ng2-file-upload/blob/master/LICENSE) file for the full text) The MIT License (see the [LICENSE](https://github.com/valor-software/ng2-chunk-file-upload/blob/master/LICENSE) file for the full text)

114
angular.json Normal file
View File

@@ -0,0 +1,114 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"ng2-chunk-file-upload": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "demo/dist",
"index": "demo/src/index.html",
"main": "demo/src/main.ts",
"tsConfig": "demo/src/tsconfig.json",
"assets": [
"demo/src/assets"
],
"styles": [],
"scripts": []
},
"configurations": {
"production": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [
{
"replace": "demo/src/environments/environment.ts",
"with": "demo/src/environments/environment.prod.ts"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "ng2-chunk-file-upload:build"
},
"configurations": {
"production": {
"browserTarget": "ng2-chunk-file-upload:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "ng2-chunk-file-upload:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "demo/src/../../scripts/test.ts",
"karmaConfig": "karma.conf.js",
"scripts": [],
"styles": [],
"assets": [
"demo/src/assets"
]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [],
"exclude": []
}
}
}
},
"ng2-chunk-file-upload-e2e": {
"root": "",
"sourceRoot": "",
"projectType": "application",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "protractor.conf.js",
"devServerTarget": "ng2-chunk-file-upload:serve"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [],
"exclude": []
}
}
}
}
},
"defaultProject": "ng2-chunk-file-upload",
"schematics": {
"@schematics/angular:component": {
"prefix": "",
"styleext": "css"
},
"@schematics/angular:directive": {
"prefix": ""
}
}
}

View File

@@ -3,41 +3,49 @@ import { Component } from '@angular/core';
let gettingStarted = require('html-loader!markdown-loader!../getting-started.md'); let gettingStarted = require('html-loader!markdown-loader!../getting-started.md');
@Component({ @Component({
selector: 'app', selector: 'app',
template: ` template: `
<main class="bd-pageheader"> <main class="bd-pageheader">
<div class="container"> <div class="container">
<h1>ng2-file-upload</h1> <h1>ng2-chunk-file-upload</h1>
<p>The Angular2 File Upload directives</p> <p>The Angular2 File Upload directives</p>
<a class="btn btn-primary" href="https://github.com/valor-software/ng2-file-upload">View on GitHub</a> <a class="btn btn-primary" href="https://github.com/valor-software/ng2-chunk-file-upload">View on GitHub</a>
<div class="row"> <div class="row">
<div class="col-lg-1"><iframe src="https://ghbtns.com/github-btn.html?user=valor-software&repo=ng2-file-upload&type=star&count=true" frameborder="0" scrolling="0" width="170px" height="20px"></iframe></div> <div class="col-lg-1">
<div class="col-lg-1"><iframe src="https://ghbtns.com/github-btn.html?user=valor-software&repo=ng2-file-upload&type=fork&count=true" frameborder="0" scrolling="0" width="170px" height="20px"></iframe></div> <iframe src="https://ghbtns.com/github-btn.html?user=valor-software&repo=ng2-chunk-file-upload&type=star&count=true"
</div> frameborder="0" scrolling="0" width="170px" height="20px"></iframe>
</div> </div>
</main> <div class="col-lg-1">
<iframe src="https://ghbtns.com/github-btn.html?user=valor-software&repo=ng2-chunk-file-upload&type=fork&count=true"
frameborder="0" scrolling="0" width="170px" height="20px"></iframe>
</div>
</div>
</div>
</main>
<div class="container"> <div class="container">
<section id="getting-started" [innerHtml]="gettingStarted"></section> <section id="getting-started" [innerHtml]="gettingStarted"></section>
<file-upload-section class="col-md-12"></file-upload-section> <file-upload-section class="col-md-12"></file-upload-section>
</div> </div>
<footer class="footer"> <footer class="footer">
<div class="container"> <div class="container">
<p class="text-muted text-center"><a href="https://github.com/valor-software/ng2-file-upload">ng2-file-upload</a> is maintained by <a href="https://github.com/valor-software">valor-software</a>.</p> <p class="text-muted text-center">
</div> <a href="https://github.com/valor-software/ng2-chunk-file-upload">ng2-chunk-file-upload</a>
</footer> is maintained by <a href="https://github.com/valor-software">valor-software</a>.</p>
` </div>
</footer>
`,
}) })
export class AppComponent { export class AppComponent {
public gettingStarted:string = gettingStarted; public gettingStarted: string = gettingStarted;
public ngAfterContentInit(): any { public ngAfterContentInit(): any {
setTimeout(()=>{ setTimeout(() => {
if (typeof PR !== 'undefined') { if (typeof PR !== 'undefined') {
// google code-prettify // google code-prettify
PR.prettyPrint(); PR.prettyPrint();
} }
}, 150); }, 150);
} }
} }

View File

@@ -4,16 +4,24 @@ import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from '@angular/platform-browser';
import { TabsModule } from 'ngx-bootstrap/tabs'; import { TabsModule } from 'ngx-bootstrap/tabs';
import { FileUploadModule } from 'ng2-file-upload'; import { FileUploadModule } from '../../../src/file-upload/file-upload.module';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { FileUploadSectionComponent } from './components/file-upload-section'; import { FileUploadSectionComponent } from './components/file-upload-section';
import { SimpleDemoComponent } from './components/file-upload/simple-demo'; import { SimpleDemoComponent } from './components/file-upload/simple-demo';
import { HttpModule } from '@angular/http';
@NgModule({ @NgModule({
imports: [BrowserModule, CommonModule, FileUploadModule, TabsModule.forRoot(), FormsModule], imports: [
declarations: [AppComponent, FileUploadSectionComponent, SimpleDemoComponent], HttpModule,
bootstrap: [AppComponent] BrowserModule,
CommonModule,
FileUploadModule,
TabsModule.forRoot(),
FormsModule,
],
declarations: [AppComponent, FileUploadSectionComponent, SimpleDemoComponent],
bootstrap: [AppComponent],
}) })
export class AppModule { export class AppModule {}
}

View File

@@ -2,28 +2,28 @@ import { Component } from '@angular/core';
let doc = require('html-loader!markdown-loader!../../doc.md'); let doc = require('html-loader!markdown-loader!../../doc.md');
let tabDesc:Array<any> = [ let tabDesc: Array<any> = [
{ {
heading: 'Simple', heading: 'Simple',
ts: require('!!raw-loader?lang=typescript!./file-upload/simple-demo.ts'), ts: require('!!raw-loader?lang=typescript!./file-upload/simple-demo.ts'),
html: require('!!raw-loader?lang=markup!./file-upload/simple-demo.html'), html: require('!!raw-loader?lang=markup!./file-upload/simple-demo.html'),
js: require('!!raw-loader?lang=javascript!./file-upload/file-catcher.js') js: require('!!raw-loader?lang=javascript!./file-upload/file-catcher.js')
} }
]; ];
@Component({ @Component({
selector: 'file-upload-section', selector: 'file-upload-section',
templateUrl: './file-upload-section.html' templateUrl: './file-upload-section.html'
}) })
export class FileUploadSectionComponent { export class FileUploadSectionComponent {
public name:string = 'File Upload'; public name: string = 'File Upload';
public currentHeading:string = 'Simple'; public currentHeading: string = 'Simple';
public doc:string = doc; public doc: string = doc;
public tabs:any = tabDesc; public tabs: any = tabDesc;
public select(e:any):void { public select(e: any): void {
if (e.heading) { if (e.heading) {
this.currentHeading = e.heading; this.currentHeading = e.heading;
} }
} }
} }

View File

@@ -1,5 +1,5 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { FileUploader } from 'ng2-file-upload'; import { FileUploader } from 'ng2-chunk-file-upload';
// const URL = '/api/'; // const URL = '/api/';
const URL = 'https://evening-anchorage-3159.herokuapp.com/api/'; const URL = 'https://evening-anchorage-3159.herokuapp.com/api/';

View File

@@ -1,6 +1,6 @@
### Usage ### Usage
```typescript ```typescript
import { FileSelectDirective, FileDropDirective, FileUploader } from 'ng2-file-upload/ng2-file-upload'; import { FileSelectDirective, FileDropDirective, FileUploader } from 'ng2-chunk-file-upload/ng2-chunk-file-upload';
``` ```
### Annotations ### Annotations
@@ -18,7 +18,7 @@ import { FileSelectDirective, FileDropDirective, FileUploader } from 'ng2-file-u
### Properties ### Properties
- `uploader` - (`FileUploader`) - uploader object. See using in [demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.ts) - `uploader` - (`FileUploader`) - uploader object. See using in [demo](https://github.com/valor-software/ng2-chunk-file-upload/blob/master/demo/components/file-upload/simple-demo.ts)
Parameters supported by this object: Parameters supported by this object:
@@ -37,11 +37,11 @@ import { FileSelectDirective, FileDropDirective, FileUploader } from 'ng2-file-u
### Properties ### Properties
- `uploader` - (`FileUploader`) - uploader object. See using in [demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.ts) - `uploader` - (`FileUploader`) - uploader object. See using in [demo](https://github.com/valor-software/ng2-chunk-file-upload/blob/master/demo/components/file-upload/simple-demo.ts)
### Events ### Events
- `fileOver` - it fires during 'over' and 'out' events for Drop Area; returns `boolean`: `true` if file is over Drop Area, `false` in case of out. - `fileOver` - it fires during 'over' and 'out' events for Drop Area; returns `boolean`: `true` if file is over Drop Area, `false` in case of out.
See using in [ts demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.ts) and See using in [ts demo](https://github.com/valor-software/ng2-chunk-file-upload/blob/master/demo/components/file-upload/simple-demo.ts) and
[html demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.html) [html demo](https://github.com/valor-software/ng2-chunk-file-upload/blob/master/demo/components/file-upload/simple-demo.html)
- `onFileDrop` - it fires after a file has been dropped on a Drop Area; you can pass in `$event` to get the list of files that were dropped. i.e. `(onFileDrop)="dropped($event)"` - `onFileDrop` - it fires after a file has been dropped on a Drop Area; you can pass in `$event` to get the list of files that were dropped. i.e. `(onFileDrop)="dropped($event)"`

View File

@@ -6,5 +6,5 @@
Install the components Install the components
``` ```
npm install ng2-file-upload --save npm install ng2-chunk-file-upload --save
``` ```

View File

@@ -9,7 +9,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:;base64,iVBORw0KGgo="> <link rel="icon" href="data:;base64,iVBORw0KGgo=">
<link rel="author" href="https://github.com/valor-software/ng2-file-upload/graphs/contributors"> <link rel="author" href="https://github.com/valor-software/ng2-chunk-file-upload/graphs/contributors">
<!--link to bootstrap.css--> <!--link to bootstrap.css-->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

View File

@@ -1,22 +1,17 @@
{ {
"compilerOptions": { "compilerOptions": {
"declaration": false, "declaration": false,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"noEmitHelpers": false, "noEmitHelpers": false,
"lib": ["es6", "dom"], "lib": ["es6", "dom"],
"types": [ "types": ["jasmine", "webpack"],
"jasmine", "mapRoot": "./",
"webpack" "module": "es6",
], "moduleResolution": "node",
"mapRoot": "./", "outDir": "../temp/out-tsc",
"module": "es6", "sourceMap": true,
"moduleResolution": "node", "target": "es5",
"outDir": "../temp/out-tsc", "typeRoots": ["../node_modules/@types"]
"sourceMap": true, }
"target": "es5",
"typeRoots": [
"../node_modules/@types"
]
}
} }

View File

@@ -6,21 +6,21 @@ const customLaunchers = require('./scripts/sauce-browsers').customLaunchers;
module.exports = function (config) { module.exports = function (config) {
const configuration = { const configuration = {
basePath: '', basePath: '',
frameworks: ['jasmine', '@angular/cli'], frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [ plugins: [
require('karma-jasmine'), require('karma-jasmine'),
require('karma-chrome-launcher'), require('karma-chrome-launcher'),
require('karma-coverage-istanbul-reporter'), require('karma-coverage-istanbul-reporter'),
require('@angular/cli/plugins/karma') require('@angular-devkit/build-angular/plugins/karma')
], ],
files: [ files: [
{pattern: './scripts/test.ts', watched: false} {pattern: './scripts/test.ts', watched: false}
], ],
preprocessors: { preprocessors: {
'./scripts/test.ts': ['@angular/cli'] './scripts/test.ts': ['@angular-devkit/build-angular']
}, },
coverageIstanbulReporter: { coverageIstanbulReporter: {
reports: [ 'html', 'lcovonly' ], dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: false fixWebpackSourcePaths: false
}, },
angularCli: { angularCli: {
@@ -48,7 +48,6 @@ module.exports = function (config) {
if (process.env.TRAVIS) { if (process.env.TRAVIS) {
configuration.browsers = ['Chrome_travis_ci']; configuration.browsers = ['Chrome_travis_ci'];
configuration.singleRun = true;
} }
if (process.env.SAUCE) { if (process.env.SAUCE) {

17621
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
{ {
"name": "ng2-file-upload-base", "name": "ng2-chunk-file-upload-base",
"version": "1.3.0", "version": "1.3.0",
"private": true, "private": true,
"description": "Angular file upload directives", "description": "Angular file upload directives with Chunk Upload",
"scripts": { "scripts": {
"lite-server": "lite-server -c demo/bs-config.json", "lite-server": "lite-server -c demo/bs-config.json",
"demo.serve": "run-s build link demo.build lite-server", "demo.serve": "run-s build link demo.build lite-server",
@@ -22,7 +22,7 @@
"test-coverage": "ng test -sr -cc", "test-coverage": "ng test -sr -cc",
"version": "npm run flow.changelog && git add -A" "version": "npm run flow.changelog && git add -A"
}, },
"main": "bundles/ng2-file-upload.umd.js", "main": "bundles/ng2-chunk-file-upload.umd.js",
"module": "index.js", "module": "index.js",
"typings": "index.d.ts", "typings": "index.d.ts",
"keywords": [ "keywords": [
@@ -31,89 +31,98 @@
"angularjs", "angularjs",
"twitter-bootstrap", "twitter-bootstrap",
"file-upload", "file-upload",
"angular-file-upload" "angular-file-upload",
"chunk-file-upload",
"azure-blob-storage"
], ],
"author": "Vyacheslav Chub <vyacheslav.chub@valor-software.com>", "author": "Paulo Peres Jr <paulo@myog.io>",
"license": "MIT", "license": "MIT",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+ssh://git@github.com/valor-software/ng2-file-upload.git" "url": "git+ssh://git@github.com/PauloPeres/ng2-chunk-file-upload.git"
}, },
"bugs": { "bugs": {
"url": "https://github.com/valor-software/ng2-file-upload/issues" "url": "https://github.com/PauloPeres/ng2-chunk-file-upload/issues"
}, },
"homepage": "https://github.com/valor-software/ng2-file-upload#readme", "homepage": "https://github.com/PauloPeres/ng2-chunk-file-upload#readme",
"dependencies": {}, "dependencies": {},
"peerDependencies": { "peerDependencies": {
"@angular/common": "^2.3.1 || >=4.0.0", "@angular/common": "^4.3.0 || >=4.3.0",
"@angular/core": "^2.3.1 || >=4.0.0" "@angular/core": "^4.3.0 || >=4.3.0",
"@angular/http": "^4.3.0 || >=4.3.0"
}, },
"devDependencies": { "devDependencies": {
"@angular/cli": "1.0.0", "@angular-devkit/build-angular": "~0.6.3",
"@angular/common": "2.4.3", "@angular/cdk": "^6.1.0",
"@angular/compiler": "2.4.3", "@angular/cli": "^6.0.3",
"@angular/compiler-cli": "2.4.3", "@angular/common": "^6.0.1",
"@angular/core": "2.4.3", "@angular/compiler": "^6.0.1",
"@angular/forms": "2.4.3", "@angular/compiler-cli": "^6.0.1",
"@angular/http": "2.4.3", "@angular/core": "^6.0.1",
"@angular/language-service": "2.4.3", "@angular/forms": "^6.0.1",
"@angular/platform-browser": "2.4.3", "@angular/http": "^6.0.1",
"@angular/platform-browser-dynamic": "2.4.3", "@angular/language-service": "^6.0.1",
"@angular/router": "3.4.3", "@angular/material": "^6.1.0",
"@angular/tsc-wrapped": "0.5.1", "@angular/platform-browser": "^6.0.1",
"@types/jasmine": "2.5.40", "@angular/platform-browser-dynamic": "^6.0.1",
"@types/marked": "0.0.28", "@angular/router": "^6.0.1",
"@types/node": "7.0.0", "@angular/tsc-wrapped": "4.4.6",
"@types/webpack": "^2.2.1", "@types/jasmine": "2.8.7",
"bootstrap": "3.3.7", "@types/marked": "0.3.0",
"@types/node": "10.1.2",
"@types/webpack": "^4.4.0",
"ajv": "^6.0.0",
"bootstrap": "4.1.1",
"chokidar-cli": "1.2.0", "chokidar-cli": "1.2.0",
"classlist-polyfill": "1.0.3", "classlist-polyfill": "1.2.0",
"codecov": "1.0.1", "codecov": "3.0.2",
"codelyzer": "~2.0.0-beta.4", "codelyzer": "~4.3.0",
"conventional-changelog-cli": "1.2.0", "conventional-changelog-cli": "1.3.22",
"conventional-github-releaser": "1.1.3", "conventional-github-releaser": "2.0.2",
"core-js": "^2.4.1", "core-js": "^2.4.1",
"cpy": "5.0.0", "cpy": "7.0.0",
"cpy-cli": "1.0.1", "cpy-cli": "1.0.1",
"del-cli": "0.2.1", "del-cli": "1.1.0",
"gh-pages": "0.12.0", "gh-pages": "1.1.0",
"gitignore-to-glob": "0.3.0", "gitignore-to-glob": "0.3.0",
"google-code-prettify": "1.0.5", "google-code-prettify": "1.0.5",
"html-loader": "0.4.4", "html-loader": "0.5.5",
"jasmine": "2.5.3", "jasmine": "3.1.0",
"jasmine-core": "2.5.2", "jasmine-core": "3.1.0",
"jasmine-data-provider": "2.2.0", "jasmine-data-provider": "2.2.0",
"jasmine-spec-reporter": "3.2.0", "jasmine-spec-reporter": "4.2.1",
"karma": "^4.2.0", "jquery": "^1.9.1",
"karma-chrome-launcher": "^3.1.0", "karma": "2.0.2",
"karma-chrome-launcher": "^2.0.0",
"karma-cli": "^1.0.1", "karma-cli": "^1.0.1",
"karma-coverage-istanbul-reporter": "^1.3.0", "karma-coverage-istanbul-reporter": "^2.0.1",
"karma-jasmine": "^1.0.2", "karma-jasmine": "^1.0.2",
"karma-remap-istanbul": "0.4.0", "karma-remap-istanbul": "0.6.0",
"karma-sauce-launcher": "1.1.0", "karma-sauce-launcher": "1.2.0",
"lite-server": "2.2.2", "lite-server": "2.3.0",
"lodash": "4.17.4", "lodash": "4.17.10",
"markdown-loader": "^0.1.7", "markdown-loader": "^2.0.2",
"marked": "0.3.6", "marked": "0.4.0",
"ng2-page-scroll": "4.0.0-beta.2", "ngm-cli": "1.0.4",
"ngm-cli": "0.4.0", "ngx-bootstrap": "3.0.0",
"ngx-bootstrap": "1.6.6",
"npm-run-all": "^4.0.1", "npm-run-all": "^4.0.1",
"popper.js": "^1.14.3",
"pre-commit": "1.2.2", "pre-commit": "1.2.2",
"protractor": "5.0.0", "protractor": "5.3.2",
"reflect-metadata": "0.1.9", "reflect-metadata": "0.1.12",
"require-dir": "0.3.1", "require-dir": "1.0.0",
"rxjs": "5.0.3", "rxjs": "^6.2.0",
"systemjs-builder": "0.15.34", "rxjs-compat": "^6.1.0",
"rxjs-tslint": "^0.1.4",
"systemjs-builder": "0.16.13",
"ts-helpers": "^1.1.1", "ts-helpers": "^1.1.1",
"ts-node": "2.0.0", "ts-node": "6.0.3",
"tslint": "4.3.1", "tslint": "5.10.0",
"tslint-config-valorsoft": "1.2.0", "typedoc": "0.11.1",
"typedoc": "0.5.5", "typescript": "^2.7.2",
"typescript": "2.1.5", "wallaby-webpack": "3.9.8",
"wallaby-webpack": "0.0.30", "webdriver-manager": "12.0.6",
"webdriver-manager": "11.1.1", "zone.js": "0.8.26"
"zone.js": "0.7.5"
}, },
"contributors": [ "contributors": [
{ {
@@ -135,6 +144,11 @@
"name": "Oleksandr Telnov", "name": "Oleksandr Telnov",
"email": "otelnov@gmail.com", "email": "otelnov@gmail.com",
"url": "https://github.com/otelnov" "url": "https://github.com/otelnov"
},
{
"name": "Paulo Peres Jr",
"email": "paulo@myog.io",
"url": "https://github.com/PauloPeres/"
} }
] ]
} }

View File

@@ -0,0 +1,242 @@
export class FileChunk {
public stepSize: number = 1024 * 1024 * 3;
public rawFile: any = null;
public uploadProgress: number = null;
public uploading: boolean = null;
public uploadComplete: boolean = null;
public byteStepSize: number = null;
public totalSize: number = null;
public startByte: number = null;
public endByte: number = null;
public currentChunk: number = 0;
public totalChunks: number = null;
public uniqueIdentifier: string = null;
public totalSent: number = null;
public extraData: any = {};
constructor(rawFile: any, options: any = {}) {
this.setByteStepSize(this.stepSize);
if (typeof options !== 'undefined') {
if (typeof options.byteStepSize !== 'undefined') {
this.setByteStepSize(options.byteStepSize);
}
}
this.setRawFile(rawFile);
this.setRawFile(rawFile);
this.setUploadProgress(0);
this.setUploading(false);
this.setUploadComplete(false);
this.setTotalSize(this.getRawFile().size);
this.setStartByte(0);
this.setEndByte(this.getByteStepSize());
this.setCurrentChunk(0);
if (!this.getBrowserSliceMethod()) {
this.setTotalChunks(1);
} else {
this.setTotalChunks(Math.ceil(this.totalSize / this.byteStepSize));
}
this.setUniqueIdenfier(this.generateUniqueIdentifier());
this.setTotalSent(0);
}
public setExtraData(index: any, value: any) {
this.extraData[index] = value;
}
public getExtraData(index: any) {
return this.extraData[index];
}
//getters and setters
public setProgress(v: number) {
this.uploadProgress = v;
}
public getProgress():number {
return this.uploadProgress;
}
public setUploading(v: boolean) {
this.uploading = v;
}
public getUploading():boolean {
return this.uploading;
}
public getUploadComplete():boolean {
return this.uploadComplete;
}
public setUploadComplete(v: boolean) {
this.uploadComplete = v;
}
public setUploadProgress(v: number) {
this.uploadProgress = v;
}
public getUploadProgress():number {
return this.uploadProgress;
}
public getStartByte():number {
return this.startByte;
}
public setStartByte(v: number) {
this.startByte = v;
}
public getEndByte():number {
return this.endByte;
}
public setEndByte(v: number) {
this.endByte = v;
}
public getByteStepSize():number {
return this.byteStepSize;
}
public setByteStepSize(v: number) {
this.byteStepSize = v;
}
public setTotalSize(v: number) {
this.totalSize = v;
}
public getTotalSize():number {
return this.totalSize;
}
public getRawFile():any {
return this.rawFile;
}
public setRawFile(v: File) {
this.rawFile = v;
}
public getCurrentChunk():number {
return this.currentChunk;
}
public setCurrentChunk(v: number) {
this.currentChunk = v;
}
public getTotalChunks():number {
return this.totalChunks;
}
public setTotalChunks(v: number) {
this.totalChunks = v;
}
public setUniqueIdenfier(v: string) {
this.uniqueIdentifier = v;
}
public getUniqueIdenfier():string {
return this.uniqueIdentifier;
}
public getRawFileExtension() {
const extension = this.getRawFileName().split('.');
return extension[extension.length - 1];
}
public getRawFileName() {
return this.getRawFile().name;
}
public getContentType() {
return this.getRawFile().type;
}
public getTotalSent() {
return this.totalSent;
}
public setTotalSent(v: number) {
this.totalSent = v;
}
public getCurrentRawFileChunk() {
if (!this.getBrowserSliceMethod()) {
return this.getRawFile();
}
else {
return this.getRawFile()[this.getBrowserSliceMethod()](this.getStartByte(), this.getEndByte());
}
}
public retrocedeChunk() {
if (!this.getBrowserSliceMethod()) {
return false;
}
this.setEndByte(this.getStartByte());
this.setStartByte(this.getStartByte() - this.getByteStepSize());
this.setCurrentChunk(this.getCurrentChunk() - 1);
if (this.getTotalSent() != 0) {
this.setTotalSent(this.getTotalSent() - this.getByteStepSize());
}
}
public prepareNextChunk() {
if (!this.getBrowserSliceMethod()) {
return false;
}
if (this.getEndByte() > this.getTotalSize() && this.getCurrentChunk() < this.getTotalChunks()) { // finished
return false;
}
this.setStartByte(this.getEndByte());
this.setEndByte(this.getEndByte() + this.getByteStepSize());
this.setCurrentChunk(this.getCurrentChunk() + 1);
if (this.getEndByte() > this.getTotalSize() && this.getCurrentChunk() === this.getTotalChunks()) {
// something went wrong with the calculations
this.setEndByte(this.getTotalSize());
}
return true;
}
public getBrowserSliceMethod(): string {
if (this.rawFile && typeof this.rawFile !== 'undefined') {
if (this.rawFile.slice && typeof this.rawFile.slice === 'function') {
return 'slice';
}
else if (this.rawFile.mozSlice && typeof this.rawFile.mozSlice === 'function') {
return 'mozSlice';
}
else if (this.rawFile.webkitSlice && typeof this.rawFile.webkitSlice === 'function') {
return 'webkitSlice';
}
}
else {
return null;
}
}//getBrowserSliceMethod() ends here
public generateUniqueIdentifier(): string {
let d = new Date().getTime();
if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
d += performance.now(); // use high-precision timer if available
}
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
}
}

View File

@@ -1,91 +1,86 @@
import { Directive, ElementRef, EventEmitter, HostListener, Input, Output } from '@angular/core'; import { Directive, EventEmitter, ElementRef, HostListener, Input, Output } from '@angular/core';
import { FileUploader, FileUploaderOptions, FilterFunction } from './file-uploader.class'; import { FileUploader, FileUploaderOptions } from './file-uploader.class';
@Directive({ selector: '[ng2FileDrop]' }) @Directive({ selector: '[ng2FileDrop]' })
export class FileDropDirective { export class FileDropDirective {
@Input() public uploader: FileUploader; @Input() public uploader: FileUploader;
// tslint:disable-next-line:no-input-rename @Output() public fileOver: EventEmitter<any> = new EventEmitter();
@Input('ng2FileFilter') public filter: FilterFunction['fn']; @Output() public onFileDrop: EventEmitter<File[]> = new EventEmitter<File[]>();
@Output() public fileOver: EventEmitter<any> = new EventEmitter();
@Output() public onFileDrop: EventEmitter<FileList> = new EventEmitter<FileList>();
protected element: ElementRef; protected element: ElementRef;
public constructor(element: ElementRef) { public constructor(element: ElementRef) {
this.element = element; this.element = element;
} }
public getOptions(): FileUploaderOptions { public getOptions(): FileUploaderOptions {
return this.uploader.options; return this.uploader.options;
} }
public getFilters(): any { public getFilters(): any {
return {}; return {};
} }
@HostListener('drop', ['$event']) @HostListener('drop', ['$event'])
public onDrop(event: any): void { public onDrop(event: any): void {
let transfer = this._getTransfer(event); let transfer = this._getTransfer(event);
if (!transfer) { if (!transfer) {
return; return;
} }
let options = this.getOptions(); let options = this.getOptions();
let filters = typeof this.filter === 'function' ? [{ let filters = this.getFilters();
name: 'ng2FileDropDirectiveFilter', this._preventAndStop(event);
fn: this.filter this.uploader.addToQueue(transfer.files, options, filters);
}, ...options.filters] : this.getFilters(); this.fileOver.emit(false);
this._preventAndStop(event); this.onFileDrop.emit(transfer.files);
this.uploader.addToQueue(transfer.files, options, filters); }
this.fileOver.emit(false);
this.onFileDrop.emit(transfer.files);
}
@HostListener('dragover', ['$event']) @HostListener('dragover', ['$event'])
public onDragOver(event: any): void { public onDragOver(event: any): void {
let transfer = this._getTransfer(event); let transfer = this._getTransfer(event);
if (!this._haveFiles(transfer.types)) { if (!this._haveFiles(transfer.types)) {
return; return;
} }
transfer.dropEffect = 'copy'; transfer.dropEffect = 'copy';
this._preventAndStop(event); this._preventAndStop(event);
this.fileOver.emit(true); this.fileOver.emit(true);
} }
@HostListener('dragleave', ['$event']) @HostListener('dragleave', ['$event'])
public onDragLeave(event: any): any { public onDragLeave(event: any): any {
if ((this as any).element) { if ((this as any).element) {
if (event.currentTarget === (this as any).element[0]) { if (event.currentTarget === (this as any).element[0]) {
return; return;
} }
} }
this._preventAndStop(event); this._preventAndStop(event);
this.fileOver.emit(false); this.fileOver.emit(false);
} }
protected _getTransfer(event: any): DragEvent['dataTransfer'] { protected _getTransfer(event: any): any {
return event.dataTransfer ? event.dataTransfer : event.originalEvent.dataTransfer; // jQuery fix; return event.dataTransfer ? event.dataTransfer : event.originalEvent.dataTransfer; // jQuery fix;
} }
protected _preventAndStop(event: Event): any { protected _preventAndStop(event: any): any {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
} }
protected _haveFiles(types: any): any { protected _haveFiles(types: any): any {
if (!types) { if (!types) {
return false; return false;
} }
if (types.indexOf) { if (types.indexOf) {
return types.indexOf('Files') !== -1; return types.indexOf('Files') !== -1;
} else if (types.contains) { } else if (types.contains) {
return types.contains('Files'); return types.contains('Files');
} else { } else {
return false; return false;
} }
} }
} }

View File

@@ -1,154 +1,210 @@
import { HttpHeaders } from '@angular/common/http';
import { FileLikeObject } from './file-like-object.class'; import { FileLikeObject } from './file-like-object.class';
import { FileUploader, ParsedResponseHeaders, FileUploaderOptions } from './file-uploader.class'; import { FileUploader, FileUploaderOptions } from './file-uploader.class';
import { FileChunk } from './file-chunk.class'
export class FileItem { export class FileItem {
public file: FileLikeObject; public file: FileLikeObject;
public _file: File; public _file: File;
public alias: string; public id: any;
public url: string = '/'; public alias: string;
public method: string; public url: string = '/';
public headers: any = []; public method: string;
public withCredentials: boolean = true; public headers: any = [];
public formData: any = []; public withCredentials: boolean = true;
public isReady: boolean = false; public formData: any = [];
public isUploading: boolean = false; public isReady: boolean = false;
public isUploaded: boolean = false; public isUploading: boolean = false;
public isSuccess: boolean = false; public isUploaded: boolean = false;
public isCancel: boolean = false; public isSuccess: boolean = false;
public isError: boolean = false; public isCancel: boolean = false;
public progress: number = 0; public isError: boolean = false;
public index: number = void 0; public isRemoving: boolean = false;
public _xhr: XMLHttpRequest; public progress: number = 0;
public _form: any; public index: number = void 0;
public downloadUrl?: string = null;
public _form: any;
public _fileChunks: FileChunk;
protected chunkTotalRetries = 10;
protected chunkRetries = 0;
protected uploader: FileUploader;
protected some: File;
protected options: FileUploaderOptions;
protected uploader: FileUploader; public constructor(uploader: FileUploader, some: File, options: FileUploaderOptions) {
protected some: File; this.uploader = uploader;
protected options: FileUploaderOptions; this.some = some;
this.options = options;
this.file = new FileLikeObject(some);
this._file = some;
public constructor(uploader: FileUploader, some: File, options: FileUploaderOptions) { if (uploader.options) {
this.uploader = uploader; this.method = uploader.options.method || 'POST';
this.some = some; this.alias = uploader.options.itemAlias || 'file';
this.options = options; }
this.file = new FileLikeObject(some); this.url = uploader.options.url;
this._file = some; }
if (uploader.options) { public upload(): void {
this.method = uploader.options.method || 'POST'; try {
this.alias = uploader.options.itemAlias || 'file'; this.uploader.uploadItem(this);
} } catch (e) {
this.url = uploader.options.url; this.uploader._onCompleteItem(this, '', 0, new HttpHeaders());
} this.uploader._onErrorItem(this, '', 0, new HttpHeaders());
}
}
public createFileChunk(chunkSize: number): void {
this.fileChunks = new FileChunk(this._file, { byteStepSize: chunkSize });
}
public getCurrentChunkFile(): any {
return this.fileChunks.getCurrentRawFileChunk();
}
public prepareNextChunk(): void {
this.fileChunks.prepareNextChunk();
}
public getCurrentChunk(): number {
return this.fileChunks.getCurrentChunk()
}
public getTotalChunks(): number {
return this.fileChunks.getTotalChunks()
}
public setIsUploading(val: boolean) {
this.isUploading = val;
if (this.fileChunks) {
this.fileChunks.setUploading(val)
}
}
public set fileChunks(val: FileChunk) {
this._fileChunks = val;
}
public get fileChunks(): FileChunk {
return this._fileChunks;
}
public getId(): any {
return this.id;
}
public setId(id: any) {
this.id = id;
}
public cancel(): void {
this.uploader.cancelItem(this);
}
public remove(): void {
this.uploader.removeFromQueue(this);
}
public removeOnline(): void {
this.isRemoving = true;
this.uploader.uploaderService.deleteEntry(this,{},true).subscribe(
(result:any) => {
this.isRemoving = false;
this.remove();
},
(error:any) => {
this.isRemoving = false;
}
);
}
public onBeforeUpload(): void {
return void 0;
}
public onBuildForm(form: any): any {
return { form };
}
public onProgress(progress: number): any {
return { progress };
}
public onSuccess(response: string, status: number, headers: HttpHeaders): any {
return { response, status, headers };
}
public onError(response: string, status: number, headers: HttpHeaders): any {
return { response, status, headers };
}
public onCancel(): any {
return {};
}
public onComplete(response: string, status: number, headers: HttpHeaders): any {
return { response, status, headers };
}
public onCompleteChunk(response: string, status: number, headers: HttpHeaders): any {
return { response, status, headers };
}
public _onBeforeUpload(): void {
this.isReady = true;
this.isUploading = true;
this.isUploaded = false;
this.isSuccess = false;
this.isCancel = false;
this.isError = false;
this.progress = 0;
this.onBeforeUpload();
}
public _onBuildForm(form: any): void {
this.onBuildForm(form);
}
public _onProgress(progress: number): void {
this.progress = progress;
this.onProgress(progress);
}
public _onSuccess(response: string, status: number, headers: HttpHeaders): void {
this.isReady = false;
this.isUploading = false;
this.isUploaded = true;
this.isSuccess = true;
this.isCancel = false;
this.isError = false;
this.progress = 100;
this.index = void 0;
this.onSuccess(response, status, headers);
}
public _onError(response: string, status: number, headers: HttpHeaders): void {
this.isReady = false;
this.isUploading = false;
this.isUploaded = true;
this.isSuccess = false;
this.isCancel = false;
this.isError = true;
this.progress = 0;
this.index = void 0;
this.onError(response, status, headers);
}
public _onCancel(): void {
this.isReady = false;
this.isUploading = false;
this.isUploaded = false;
this.isSuccess = false;
this.isCancel = true;
this.isError = false;
this.progress = 0;
this.index = void 0;
this.onCancel();
}
public _onComplete(response: string, status: number, headers: HttpHeaders): void {
this.onComplete(response, status, headers);
public upload(): void { if (this.uploader.options.removeAfterUpload) {
try { this.remove();
this.uploader.uploadItem(this); }
} catch (e) { }
this.uploader._onCompleteItem(this, '', 0, {}); public _onCompleteChunk(response: string, status: number, headers: HttpHeaders): void {
this.uploader._onErrorItem(this, '', 0, {}); this.chunkRetries = 0;
} this._onCompleteChunkCallNext();
} this.onCompleteChunk(response, status, headers);
}
public cancel(): void { public _onCompleteChunkCallNext(): void {
this.uploader.cancelItem(this); this.uploader.uploaderService.uploadFile(this,this.uploader.options);
} this.prepareNextChunk()
}
public remove(): void { public _onErrorChunk(response: string, status: number, headers: HttpHeaders): void {
this.uploader.removeFromQueue(this); if (this.chunkRetries > this.chunkTotalRetries) {
} this.uploader.onErrorItem(this, response, status, headers);
this.uploader.onCompleteItem(this, response, status, headers);
public onBeforeUpload(): void { } else {
return void 0; this.chunkRetries++;
} this.fileChunks.retrocedeChunk();
this._onCompleteChunkCallNext();
public onBuildForm(form: any): any { }
return { form }; }
} public _prepareToUploading(): void {
this.index = this.index || ++this.uploader._nextIndex;
public onProgress(progress: number): any { this.isReady = true;
return { progress }; }
}
public onSuccess(response: string, status: number, headers: ParsedResponseHeaders): any {
return { response, status, headers };
}
public onError(response: string, status: number, headers: ParsedResponseHeaders): any {
return { response, status, headers };
}
public onCancel(response: string, status: number, headers: ParsedResponseHeaders): any {
return { response, status, headers };
}
public onComplete(response: string, status: number, headers: ParsedResponseHeaders): any {
return { response, status, headers };
}
public _onBeforeUpload(): void {
this.isReady = true;
this.isUploading = true;
this.isUploaded = false;
this.isSuccess = false;
this.isCancel = false;
this.isError = false;
this.progress = 0;
this.onBeforeUpload();
}
public _onBuildForm(form: any): void {
this.onBuildForm(form);
}
public _onProgress(progress: number): void {
this.progress = progress;
this.onProgress(progress);
}
public _onSuccess(response: string, status: number, headers: ParsedResponseHeaders): void {
this.isReady = false;
this.isUploading = false;
this.isUploaded = true;
this.isSuccess = true;
this.isCancel = false;
this.isError = false;
this.progress = 100;
this.index = void 0;
this.onSuccess(response, status, headers);
}
public _onError(response: string, status: number, headers: ParsedResponseHeaders): void {
this.isReady = false;
this.isUploading = false;
this.isUploaded = true;
this.isSuccess = false;
this.isCancel = false;
this.isError = true;
this.progress = 0;
this.index = void 0;
this.onError(response, status, headers);
}
public _onCancel(response: string, status: number, headers: ParsedResponseHeaders): void {
this.isReady = false;
this.isUploading = false;
this.isUploaded = false;
this.isSuccess = false;
this.isCancel = true;
this.isError = false;
this.progress = 0;
this.index = void 0;
this.onCancel(response, status, headers);
}
public _onComplete(response: string, status: number, headers: ParsedResponseHeaders): void {
this.onComplete(response, status, headers);
if (this.uploader.options.removeAfterUpload) {
this.remove();
}
}
public _prepareToUploading(): void {
this.index = this.index || ++this.uploader._nextIndex;
this.isReady = true;
}
} }

View File

@@ -1,33 +1,33 @@
function isElement(node: any): boolean { function isElement(node: any): boolean {
return !!(node && (node.nodeName || node.prop && node.attr && node.find)); return !!(node && (node.nodeName || node.prop && node.attr && node.find));
} }
export class FileLikeObject { export class FileLikeObject {
public lastModifiedDate: any; public lastModifiedDate: any;
public size: any; public size: any;
public type: string; public type: string;
public name: string; public name: string;
public rawFile: string; public rawFile: string;
public constructor(fileOrInput: any) { public constructor(fileOrInput: any) {
this.rawFile = fileOrInput; this.rawFile = fileOrInput;
let isInput = isElement(fileOrInput); let isInput = isElement(fileOrInput);
let fakePathOrObject = isInput ? fileOrInput.value : fileOrInput; let fakePathOrObject = isInput ? fileOrInput.value : fileOrInput;
let postfix = typeof fakePathOrObject === 'string' ? 'FakePath' : 'Object'; let postfix = typeof fakePathOrObject === 'string' ? 'FakePath' : 'Object';
let method = '_createFrom' + postfix; let method = '_createFrom' + postfix;
(this as any)[ method ](fakePathOrObject); (this as any)[method](fakePathOrObject);
} }
public _createFromFakePath(path: string): void { public _createFromFakePath(path: string): void {
this.lastModifiedDate = void 0; this.lastModifiedDate = void 0;
this.size = void 0; this.size = void 0;
this.type = 'like/' + path.slice(path.lastIndexOf('.') + 1).toLowerCase(); this.type = 'like/' + path.slice(path.lastIndexOf('.') + 1).toLowerCase();
this.name = path.slice(path.lastIndexOf('/') + path.lastIndexOf('\\') + 2); this.name = path.slice(path.lastIndexOf('/') + path.lastIndexOf('\\') + 2);
} }
public _createFromObject(object: { size: number, type: string, name: string }): void { public _createFromObject(object: { size: number, type: string, name: string }): void {
this.size = object.size; this.size = object.size;
this.type = object.type; this.type = object.type;
this.name = object.name; this.name = object.name;
} }
} }

View File

@@ -1,46 +1,41 @@
import { Directive, ElementRef, EventEmitter, HostListener, Input, Output } from '@angular/core'; import { Directive, EventEmitter, ElementRef, Input, HostListener, Output } from '@angular/core';
import { FileUploader, FilterFunction } from './file-uploader.class'; import { FileUploader } from './file-uploader.class';
@Directive({ selector: '[ng2FileSelect]' }) @Directive({ selector: '[ng2FileSelect]' })
export class FileSelectDirective { export class FileSelectDirective {
@Input() public uploader: FileUploader; @Input() public uploader: FileUploader;
// tslint:disable-next-line:no-input-rename @Output() public onFileSelected: EventEmitter<File[]> = new EventEmitter<File[]>();
@Input('ng2FileFilter') public filter: FilterFunction['fn'];
@Output() public onFileSelected: EventEmitter<File[]> = new EventEmitter<File[]>();
protected element: ElementRef; protected element: ElementRef;
public constructor(element: ElementRef) { public constructor(element: ElementRef) {
this.element = element; this.element = element;
} }
public getOptions(): any { public getOptions(): any {
return this.uploader.options; return this.uploader.options;
} }
public getFilters(): any { public getFilters(): any {
return {}; return {};
} }
public isEmptyAfterSelection(): boolean { public isEmptyAfterSelection(): boolean {
return !!this.element.nativeElement.attributes.multiple; return !!this.element.nativeElement.attributes.multiple;
} }
@HostListener('change') @HostListener('change')
public onChange(): any { public onChange(): any {
let files = this.element.nativeElement.files; let files = this.element.nativeElement.files;
let options = this.getOptions(); let options = this.getOptions();
let filters = typeof this.filter === 'function' ? [{ let filters = this.getFilters();
name: 'ng2FileSelectDirectiveFilter',
fn: this.filter
}, ...options.filters] : this.getFilters();
this.uploader.addToQueue(files, options, filters); this.uploader.addToQueue(files, options, filters);
this.onFileSelected.emit(files); this.onFileSelected.emit(files);
if (this.isEmptyAfterSelection()) { if (this.isEmptyAfterSelection()) {
this.element.nativeElement.value = ''; this.element.nativeElement.value = '';
} }
} }
} }

View File

@@ -1,164 +1,164 @@
import { FileLikeObject } from "../ng2-file-upload"; import { FileLikeObject } from "../ng2-chunk-file-upload";
export class FileType { export class FileType {
/* MS office */ /* MS office */
public static mime_doc: string[] = [ public static mime_doc: string[] = [
'application/msword', 'application/msword',
'application/msword', 'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.openxmlformats-officedocument.wordprocessingml.template', 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
'application/vnd.ms-word.document.macroEnabled.12', 'application/vnd.ms-word.document.macroEnabled.12',
'application/vnd.ms-word.template.macroEnabled.12' 'application/vnd.ms-word.template.macroEnabled.12'
]; ];
public static mime_xsl: string[] = [ public static mime_xsl: string[] = [
'application/vnd.ms-excel', 'application/vnd.ms-excel',
'application/vnd.ms-excel', 'application/vnd.ms-excel',
'application/vnd.ms-excel', 'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.openxmlformats-officedocument.spreadsheetml.template', 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
'application/vnd.ms-excel.sheet.macroEnabled.12', 'application/vnd.ms-excel.sheet.macroEnabled.12',
'application/vnd.ms-excel.template.macroEnabled.12', 'application/vnd.ms-excel.template.macroEnabled.12',
'application/vnd.ms-excel.addin.macroEnabled.12', 'application/vnd.ms-excel.addin.macroEnabled.12',
'application/vnd.ms-excel.sheet.binary.macroEnabled.12' 'application/vnd.ms-excel.sheet.binary.macroEnabled.12'
]; ];
public static mime_ppt: string[] = [ public static mime_ppt: string[] = [
'application/vnd.ms-powerpoint', 'application/vnd.ms-powerpoint',
'application/vnd.ms-powerpoint', 'application/vnd.ms-powerpoint',
'application/vnd.ms-powerpoint', 'application/vnd.ms-powerpoint',
'application/vnd.ms-powerpoint', 'application/vnd.ms-powerpoint',
'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'application/vnd.openxmlformats-officedocument.presentationml.template', 'application/vnd.openxmlformats-officedocument.presentationml.template',
'application/vnd.openxmlformats-officedocument.presentationml.slideshow', 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
'application/vnd.ms-powerpoint.addin.macroEnabled.12', 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
'application/vnd.ms-powerpoint.presentation.macroEnabled.12', 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
'application/vnd.ms-powerpoint.presentation.macroEnabled.12', 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12'
]; ];
/* PSD */ /* PSD */
public static mime_psd: string[] = [ public static mime_psd: string[] = [
'image/photoshop', 'image/photoshop',
'image/x-photoshop', 'image/x-photoshop',
'image/psd', 'image/psd',
'application/photoshop', 'application/photoshop',
'application/psd', 'application/psd',
'zz-application/zz-winassoc-psd' 'zz-application/zz-winassoc-psd'
]; ];
/* Compressed files */ /* Compressed files */
public static mime_compress: string[] = [ public static mime_compress: string[] = [
'application/x-gtar', 'application/x-gtar',
'application/x-gcompress', 'application/x-gcompress',
'application/compress', 'application/compress',
'application/x-tar', 'application/x-tar',
'application/x-rar-compressed', 'application/x-rar-compressed',
'application/octet-stream', 'application/octet-stream',
'application/x-zip-compressed', 'application/x-zip-compressed',
'application/zip-compressed', 'application/zip-compressed',
'application/x-7z-compressed', 'application/x-7z-compressed',
'application/gzip', 'application/gzip',
'application/x-bzip2' 'application/x-bzip2'
]; ];
public static getMimeClass(file: FileLikeObject): string { public static getMimeClass(file: FileLikeObject): string {
let mimeClass = 'application'; let mimeClass = 'application';
if (this.mime_psd.indexOf(file.type) !== -1) { if (this.mime_psd.indexOf(file.type) !== -1) {
mimeClass = 'image'; mimeClass = 'image';
} else if (file.type.match('image.*')) { } else if (file.type.match('image.*')) {
mimeClass = 'image'; mimeClass = 'image';
} else if (file.type.match('video.*')) { } else if (file.type.match('video.*')) {
mimeClass = 'video'; mimeClass = 'video';
} else if (file.type.match('audio.*')) { } else if (file.type.match('audio.*')) {
mimeClass = 'audio'; mimeClass = 'audio';
} else if (file.type === 'application/pdf') { } else if (file.type === 'application/pdf') {
mimeClass = 'pdf'; mimeClass = 'pdf';
} else if (this.mime_compress.indexOf(file.type) !== -1) { } else if (this.mime_compress.indexOf(file.type) !== -1) {
mimeClass = 'compress'; mimeClass = 'compress';
} else if (this.mime_doc.indexOf(file.type) !== -1) { } else if (this.mime_doc.indexOf(file.type) !== -1) {
mimeClass = 'doc'; mimeClass = 'doc';
} else if (this.mime_xsl.indexOf(file.type) !== -1) { } else if (this.mime_xsl.indexOf(file.type) !== -1) {
mimeClass = 'xls'; mimeClass = 'xls';
} else if (this.mime_ppt.indexOf(file.type) !== -1) { } else if (this.mime_ppt.indexOf(file.type) !== -1) {
mimeClass = 'ppt'; mimeClass = 'ppt';
} }
if (mimeClass === 'application') { if (mimeClass === 'application') {
mimeClass = this.fileTypeDetection(file.name); mimeClass = this.fileTypeDetection(file.name);
} }
return mimeClass; return mimeClass;
} }
public static fileTypeDetection(inputFilename: string): string { public static fileTypeDetection(inputFilename: string): string {
let types: { [ key: string ]: string } = { let types: { [key: string]: string } = {
'jpg': 'image', 'jpg': 'image',
'jpeg': 'image', 'jpeg': 'image',
'tif': 'image', 'tif': 'image',
'psd': 'image', 'psd': 'image',
'bmp': 'image', 'bmp': 'image',
'png': 'image', 'png': 'image',
'nef': 'image', 'nef': 'image',
'tiff': 'image', 'tiff': 'image',
'cr2': 'image', 'cr2': 'image',
'dwg': 'image', 'dwg': 'image',
'cdr': 'image', 'cdr': 'image',
'ai': 'image', 'ai': 'image',
'indd': 'image', 'indd': 'image',
'pin': 'image', 'pin': 'image',
'cdp': 'image', 'cdp': 'image',
'skp': 'image', 'skp': 'image',
'stp': 'image', 'stp': 'image',
'3dm': 'image', '3dm': 'image',
'mp3': 'audio', 'mp3': 'audio',
'wav': 'audio', 'wav': 'audio',
'wma': 'audio', 'wma': 'audio',
'mod': 'audio', 'mod': 'audio',
'm4a': 'audio', 'm4a': 'audio',
'compress': 'compress', 'compress': 'compress',
'zip': 'compress', 'zip': 'compress',
'rar': 'compress', 'rar': 'compress',
'7z': 'compress', '7z': 'compress',
'lz': 'compress', 'lz': 'compress',
'z01': 'compress', 'z01': 'compress',
'bz2': 'compress', 'bz2': 'compress',
'gz': 'compress', 'gz': 'compress',
'pdf': 'pdf', 'pdf': 'pdf',
'xls': 'xls', 'xls': 'xls',
'xlsx': 'xls', 'xlsx': 'xls',
'ods': 'xls', 'ods': 'xls',
'mp4': 'video', 'mp4': 'video',
'avi': 'video', 'avi': 'video',
'wmv': 'video', 'wmv': 'video',
'mpg': 'video', 'mpg': 'video',
'mts': 'video', 'mts': 'video',
'flv': 'video', 'flv': 'video',
'3gp': 'video', '3gp': 'video',
'vob': 'video', 'vob': 'video',
'm4v': 'video', 'm4v': 'video',
'mpeg': 'video', 'mpeg': 'video',
'm2ts': 'video', 'm2ts': 'video',
'mov': 'video', 'mov': 'video',
'doc': 'doc', 'doc': 'doc',
'docx': 'doc', 'docx': 'doc',
'eps': 'doc', 'eps': 'doc',
'txt': 'doc', 'txt': 'doc',
'odt': 'doc', 'odt': 'doc',
'rtf': 'doc', 'rtf': 'doc',
'ppt': 'ppt', 'ppt': 'ppt',
'pptx': 'ppt', 'pptx': 'ppt',
'pps': 'ppt', 'pps': 'ppt',
'ppsx': 'ppt', 'ppsx': 'ppt',
'odp': 'ppt' 'odp': 'ppt'
}; };
let chunks = inputFilename.split('.'); let chunks = inputFilename.split('.');
if (chunks.length < 2) { if (chunks.length < 2) {
return 'application'; return 'application';
} }
let extension = chunks[ chunks.length - 1 ].toLowerCase(); let extension = chunks[chunks.length - 1].toLowerCase();
if (types[ extension ] === undefined) { if (types[extension] === undefined) {
return 'application'; return 'application';
} else { } else {
return types[ extension ]; return types[extension];
} }
} }
} }

View File

@@ -5,9 +5,9 @@ import { FileDropDirective } from './file-drop.directive';
import { FileSelectDirective } from './file-select.directive'; import { FileSelectDirective } from './file-select.directive';
@NgModule({ @NgModule({
imports: [ CommonModule ], imports: [CommonModule],
declarations: [ FileDropDirective, FileSelectDirective ], declarations: [FileDropDirective, FileSelectDirective],
exports: [ FileDropDirective, FileSelectDirective ] exports: [FileDropDirective, FileSelectDirective]
}) })
export class FileUploadModule { export class FileUploadModule {
} }

View File

@@ -1,508 +1,484 @@
import { Headers } from './file-uploader.class';
import { EventEmitter } from '@angular/core'; import { EventEmitter } from '@angular/core';
import { FileLikeObject } from './file-like-object.class'; import { FileLikeObject } from './file-like-object.class';
import { FileItem } from './file-item.class'; import { FileItem } from './file-item.class';
import { FileType } from './file-type.class'; import { FileType } from './file-type.class';
import { HttpEvent, HttpResponse, HttpHeaders } from '@angular/common/http';
import { HttpUploadProgressEvent, HttpProgressEvent, HttpSentEvent, HttpErrorResponse } from '@angular/common/http/src/response';
function isFile(value: any): boolean { function isFile(value: any): boolean {
return (File && value instanceof File); return (File && value instanceof File);
} }
export interface Headers { export interface Headers {
name: string; name: string;
value: string; value: string;
} }
export type ParsedResponseHeaders = { [headerFieldName: string]: string };
export interface FilterFunction { export type FilterFunction = {
name: string; name: string,
fn(this: FileUploader, item?: FileLikeObject, options?: FileUploaderOptions, queueIndex?: number): boolean | Promise<boolean>; fn: (item?: FileLikeObject, options?: FileUploaderOptions) => boolean
}; };
export interface FileUploaderOptions { export interface FileUploaderOptions {
allowedMimeType?: string[]; uploaderService: any;
allowedFileType?: string[]; allowedMimeType?: string[];
autoUpload?: boolean; allowedFileType?: string[];
isHTML5?: boolean; autoUpload?: boolean;
filters?: FilterFunction[]; isHTML5?: boolean;
headers?: Headers[]; filters?: FilterFunction[];
method?: string; headers?: Headers[];
authToken?: string; method?: string;
maxFileSize?: number; authToken?: string;
queueLimit?: number; maxFileSize?: number;
removeAfterUpload?: boolean; queueLimit?: number;
url?: string; removeAfterUpload?: boolean;
disableMultipart?: boolean; url?: string;
itemAlias?: string; disableMultipart?: boolean;
authTokenHeader?: string; itemAlias?: string;
additionalParameter?: { [key: string]: any }; authTokenHeader?: string;
parametersBeforeFiles?: boolean; additionalParameter?: { [key: string]: any };
formatDataFunction?: Function; parametersBeforeFiles?: boolean;
formatDataFunctionIsAsync?: boolean; formatDataFunction?: Function;
formatDataFunctionIsAsync?: boolean;
} }
export class FileUploader { export class FileUploader {
public uploaderService: any;
public authToken: string; public authToken: string;
public isUploading: boolean = false; public isUploading: boolean = false;
public queue: FileItem[] = []; public queue: FileItem[] = [];
public progress: number = 0; public progress: number = 0;
public _nextIndex: number = 0; public _nextIndex: number = 0;
public autoUpload: any; public autoUpload: any;
public authTokenHeader: string; public authTokenHeader: string;
public response: EventEmitter<any>; public response: EventEmitter<any>;
public chunkSize: number = null;
public options: FileUploaderOptions = { public options: FileUploaderOptions = {
autoUpload: false, uploaderService: null,
isHTML5: true, autoUpload: false,
filters: [], isHTML5: true,
removeAfterUpload: false, filters: [],
disableMultipart: false, removeAfterUpload: false,
formatDataFunction: (item: FileItem) => item._file, disableMultipart: false,
formatDataFunctionIsAsync: false formatDataFunction: (item: FileItem) => item._file,
}; formatDataFunctionIsAsync: false
};
protected _failFilterIndex: number;
protected _failFilterIndex: number;
public constructor(options: FileUploaderOptions) {
this.setOptions(options); public constructor(options: FileUploaderOptions) {
this.response = new EventEmitter<any>(); this.setOptions(options);
} this.response = new EventEmitter<any>();
}
public setOptions(options: FileUploaderOptions): void { public setOptions(options: FileUploaderOptions): void {
this.options = Object.assign(this.options, options); this.options = Object.assign(this.options, options);
this.uploaderService = this.options.uploaderService;
this.authToken = this.options.authToken; this.uploaderService.uploader = this;
this.authTokenHeader = this.options.authTokenHeader || 'Authorization'; this.authToken = this.options.authToken;
this.autoUpload = this.options.autoUpload; this.authTokenHeader = this.options.authTokenHeader || 'Authorization';
this.options.filters.unshift({ name: 'queueLimit', fn: this._queueLimitFilter }); this.autoUpload = this.options.autoUpload;
this.options.filters.unshift({ name: 'queueLimit', fn: this._queueLimitFilter });
if (this.options.maxFileSize) {
this.options.filters.unshift({ name: 'fileSize', fn: this._fileSizeFilter }); if (this.options.maxFileSize) {
} this.options.filters.unshift({ name: 'fileSize', fn: this._fileSizeFilter });
}
if (this.options.allowedFileType) {
this.options.filters.unshift({ name: 'fileType', fn: this._fileTypeFilter }); if (this.options.allowedFileType) {
} this.options.filters.unshift({ name: 'fileType', fn: this._fileTypeFilter });
}
if (this.options.allowedMimeType) {
this.options.filters.unshift({ name: 'mimeType', fn: this._mimeTypeFilter }); if (this.options.allowedMimeType) {
} this.options.filters.unshift({ name: 'mimeType', fn: this._mimeTypeFilter });
}
for (const q of this.queue) {
q.url = this.options.url; for (let i = 0; i < this.queue.length; i++) {
} this.queue[i].url = this.options.url;
} }
}
public async addToQueue(files: FileList, options?: FileUploaderOptions, filters?: FilterFunction[] | string): Promise<void> {
let list: File[] = []; public addToQueue(files: File[], options?: FileUploaderOptions, filters?: FilterFunction[] | string): void {
// tslint:disable-next-line:prefer-for-of let list: File[] = [];
for (let i = 0; i < files.length; i++) { for (let file of files) {
list.push(files[i]); list.push(file);
} }
let arrayOfFilters = this._getFilters(filters);
let arrayOfFilters = this._getFilters(filters); let count = this.queue.length;
let count = this.queue.length; let addedFileItems: FileItem[] = [];
let addedFileItems: FileItem[] = []; list.map((some: File) => {
let idx = 0; if (!options) {
options = this.options;
for (const some of list) { }
if (!options) {
options = this.options; let temp = new FileLikeObject(some);
} if (this._isValidFile(temp, arrayOfFilters, options)) {
let fileItem = new FileItem(this, some, options);
let temp = new FileLikeObject(some); addedFileItems.push(fileItem);
if (await this._isValidFile(temp, arrayOfFilters, options, idx++)) { this.queue.push(fileItem);
let fileItem = new FileItem(this, some, options); this._onAfterAddingFile(fileItem);
addedFileItems.push(fileItem); } else {
this.queue.push(fileItem); let filter = arrayOfFilters[this._failFilterIndex];
this._onAfterAddingFile(fileItem); this._onWhenAddingFileFailed(temp, filter, options);
} else { }
let filter = arrayOfFilters[this._failFilterIndex]; });
this._onWhenAddingFileFailed(temp, filter, options); if (this.queue.length !== count) {
} this._onAfterAddingAll(addedFileItems);
} this.progress = this._getTotalProgress();
if (this.queue.length !== count) { }
this._onAfterAddingAll(addedFileItems); this._render();
this.progress = this._getTotalProgress(); if (this.options.autoUpload) {
} this.uploadAll();
this._render(); }
if (this.options.autoUpload) { }
this.uploadAll();
} public removeFromQueue(value: FileItem): void {
} let index = this.getIndexOfItem(value);
let item = this.queue[index];
public removeFromQueue(value: FileItem): void { if (item.isUploading) {
let index = this.getIndexOfItem(value); item.cancel();
let item = this.queue[index]; }
if (item.isUploading) { this.queue.splice(index, 1);
item.cancel(); this.progress = this._getTotalProgress();
} this.onRemoveItem(item);
this.queue.splice(index, 1); }
this.progress = this._getTotalProgress();
} public clearQueue(): void {
while (this.queue.length) {
public clearQueue(): void { this.queue[0].remove();
while (this.queue.length) { }
this.queue[0].remove(); this.progress = 0;
} }
this.progress = 0;
} public uploadItem(value: FileItem): void {
let index = this.getIndexOfItem(value);
public uploadItem(value: FileItem): void { let item = this.queue[index];
let index = this.getIndexOfItem(value); item._prepareToUploading();
let item = this.queue[index]; if (this.isUploading) {
let transport = this.options.isHTML5 ? '_xhrTransport' : '_iframeTransport'; return;
item._prepareToUploading(); }
if (this.isUploading) { this.isUploading = true;
return; this._uploadFile(item);
} }
this.isUploading = true;
(this as any)[transport](item); public cancelItem(value: FileItem): void {
} const index = this.getIndexOfItem(value);
const item = this.queue[index];
public cancelItem(value: FileItem): void { if (item && item.isUploading) {
let index = this.getIndexOfItem(value); this.uploaderService.stopUpload()
let item = this.queue[index]; }
let prop = this.options.isHTML5 ? item._xhr : item._form; }
if (item && item.isUploading) {
prop.abort(); public uploadAll(): void {
} const items = this.getNotUploadedItems().filter((item: FileItem) => !item.isUploading);
} if (!items.length) {
return;
public uploadAll(): void { }
let items = this.getNotUploadedItems().filter((item: FileItem) => !item.isUploading); items.map((item: FileItem) => item._prepareToUploading());
if (!items.length) { items[0].upload();
return; }
}
items.map((item: FileItem) => item._prepareToUploading()); public cancelAll(): void {
items[0].upload(); const items = this.getNotUploadedItems();
} items.map((item: FileItem) => item.cancel());
}
public cancelAll(): void {
let items = this.getNotUploadedItems(); public isFile(value: any): boolean {
items.map((item: FileItem) => item.cancel()); return isFile(value);
} }
public isFile(value: any): boolean { public isFileLikeObject(value: any): boolean {
return isFile(value); return value instanceof FileLikeObject;
} }
public isFileLikeObject(value: any): boolean { public getIndexOfItem(value: any): number {
return value instanceof FileLikeObject; return typeof value === 'number' ? value : this.queue.indexOf(value);
} }
public getIndexOfItem(value: any): number { public getIsErrorItems(): any[] {
return typeof value === 'number' ? value : this.queue.indexOf(value); return this.queue.filter((item: FileItem) => item.isError);
} }
public getNotUploadedItems(): any[] { public getIsCancelItems(): any[] {
return this.queue.filter((item: FileItem) => !item.isUploaded); return this.queue.filter((item: FileItem) => item.isCancel);
} }
public getReadyItems(): any[] { public getIsSuccessItems(): any[] {
return this.queue return this.queue.filter((item: FileItem) => item.isSuccess);
.filter((item: FileItem) => (item.isReady && !item.isUploading)) }
.sort((item1: any, item2: any) => item1.index - item2.index);
} public getAllItems(): any[] {
return this.queue;
public destroy(): void { }
return void 0;
}
public getNotUploadedItems(): any[] {
public onAfterAddingAll(fileItems: any): any { return this.queue.filter((item: FileItem) => !item.isUploaded);
return { fileItems }; }
}
public getReadyItems(): any[] {
public onBuildItemForm(fileItem: FileItem, form: any): any { return this.queue
return { fileItem, form }; .filter((item: FileItem) => (item.isReady && !item.isUploading))
} .sort((item1: any, item2: any) => item1.index - item2.index);
}
public onAfterAddingFile(fileItem: FileItem): any {
return { fileItem }; public destroy(): void {
} return void 0;
}
public onWhenAddingFileFailed(item: FileLikeObject, filter: any, options: any): any {
return { item, filter, options }; public onAfterAddingAll(fileItems: any): any {
} return { fileItems };
}
public onBeforeUploadItem(fileItem: FileItem): any {
return { fileItem }; public onBuildItemForm(fileItem: FileItem, form: any): any {
} return { fileItem, form };
}
public onProgressItem(fileItem: FileItem, progress: any): any {
return { fileItem, progress }; public onAfterAddingFile(fileItem: FileItem): any {
} return { fileItem };
}
public onProgressAll(progress: any): any {
return { progress }; public onWhenAddingFileFailed(item: FileLikeObject, filter: any, options: any): any {
} return { item, filter, options };
}
public onSuccessItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
return { item, response, status, headers }; public onBeforeUploadItem(fileItem: FileItem): any {
} return { fileItem };
}
public onErrorItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
return { item, response, status, headers }; public onProgressItem(fileItem: FileItem, progress: any): any {
} return { fileItem, progress };
}
public onCancelItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
return { item, response, status, headers }; public onProgressAll(progress: any): any {
} return { progress };
}
public onCompleteItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
return { item, response, status, headers }; public onSuccessItem(item: FileItem, response: string, status: number, headers: HttpHeaders): any {
} return { item, response, status, headers };
}
public onCompleteAll(): any {
return void 0; public onErrorItem(item: FileItem, response: string, status: number, headers: HttpHeaders): any {
} return { item, response, status, headers };
}
public _mimeTypeFilter(item: FileLikeObject): boolean {
return !(this.options.allowedMimeType && this.options.allowedMimeType.indexOf(item.type) === -1); public onCancelItem(item: FileItem): any {
} return { item };
}
public _fileSizeFilter(item: FileLikeObject): boolean { public onRemoveItem(item: FileItem): any {
return !(this.options.maxFileSize && item.size > this.options.maxFileSize); return { item };
} }
public onCompleteChunk(item: FileItem, response: string, status: number, headers: HttpHeaders): any {
public _fileTypeFilter(item: FileLikeObject): boolean { return { item, response, status, headers };
return !(this.options.allowedFileType && }
this.options.allowedFileType.indexOf(FileType.getMimeClass(item)) === -1); public onErrorChunk(item: FileItem, response: string, status: number, headers: HttpHeaders): any {
} return { item, response, status, headers };
}
public _onErrorItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): void { public onCompleteItem(item: FileItem, response: string, status: number, headers: HttpHeaders): any {
item._onError(response, status, headers); return { item, response, status, headers };
this.onErrorItem(item, response, status, headers); }
}
public onCompleteAll(): any {
public _onCompleteItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): void { return void 0;
item._onComplete(response, status, headers); }
this.onCompleteItem(item, response, status, headers);
let nextItem = this.getReadyItems()[0]; public _mimeTypeFilter(item: FileLikeObject): boolean {
this.isUploading = false; return !(this.options.allowedMimeType && this.options.allowedMimeType.indexOf(item.type) === -1);
if (nextItem) { }
nextItem.upload();
return; public _fileSizeFilter(item: FileLikeObject): boolean {
} return !(this.options.maxFileSize && item.size > this.options.maxFileSize);
this.onCompleteAll(); }
this.progress = this._getTotalProgress();
this._render(); public _fileTypeFilter(item: FileLikeObject): boolean {
} return !(this.options.allowedFileType &&
this.options.allowedFileType.indexOf(FileType.getMimeClass(item)) === -1);
protected _headersGetter(parsedHeaders: ParsedResponseHeaders): any { }
return (name: any): any => {
if (name) { public _onErrorItem(item: FileItem, response: string, status: number, headers: HttpHeaders): void {
return parsedHeaders[name.toLowerCase()] || void 0; item._onError(response, status, headers);
} this.onErrorItem(item, response, status, headers);
return parsedHeaders; }
}; public _onCompleteChunk(item: FileItem, response: string, status: number, headers: HttpHeaders): void {
} this.onCompleteChunk(item, response, status, headers);
item._onCompleteChunk(response, status, headers);
protected _xhrTransport(item: FileItem): any { this.progress = this._getTotalProgress();
let that = this; this._render();
let xhr = item._xhr = new XMLHttpRequest(); }
let sendable: any; public _onCompleteItem(item: FileItem, response?: string, status?: number, headers?: HttpHeaders): void {
this._onBeforeUploadItem(item); item._onComplete(response, status, headers);
this.onCompleteItem(item, response, status, headers);
if (typeof item._file.size !== 'number') { let nextItem = this.getReadyItems()[0];
throw new TypeError('The file specified is no longer valid'); this.isUploading = false;
} if (nextItem) {
if (!this.options.disableMultipart) { nextItem.upload();
sendable = new FormData(); return;
this._onBuildItemForm(item, sendable); }
this.onCompleteAll();
const appendFile = () => sendable.append(item.alias, item._file, item.file.name); this.progress = this._getTotalProgress();
if (!this.options.parametersBeforeFiles) { this._render();
appendFile(); }
}
protected _onProgress(event: HttpProgressEvent, item: FileItem) {
// For AWS, Additional Parameters must come BEFORE Files event = event;
if (this.options.additionalParameter !== undefined) { let progress = (100 * event.loaded / event.total);
Object.keys(this.options.additionalParameter).forEach((key: string) => { if (this.uploaderService.options.chunkSize > 0) {
let paramVal = this.options.additionalParameter[key]; progress = ( 100 * item.getCurrentChunk() / item.getTotalChunks() ) + (progress / item.getTotalChunks() );
// Allow an additional parameter to include the filename }
if (typeof paramVal === 'string' && paramVal.indexOf('{{file_name}}') >= 0) { // TODO: Check why it's not showing upload progress per item only on complete.
paramVal = paramVal.replace('{{file_name}}', item.file.name); this._onProgressItem(item, Math.round(progress) );
} }
sendable.append(key, paramVal); public onProgress(event: HttpProgressEvent, item: FileItem) {
}); this._onProgress(event, item);
} }
protected _onStart(event: HttpSentEvent, item: FileItem) {
if (this.options.parametersBeforeFiles) {
appendFile(); }
} public onStart(event: HttpSentEvent, item: FileItem) {
} else { this._onStart(event, item);
sendable = this.options.formatDataFunction(item); }
} protected _onLoad(event: HttpResponse<any>, item: FileItem) {
const headers = event.headers;
xhr.upload.onprogress = (event: any) => { const response = this._transformResponse(event.body, headers);
let progress = Math.round(event.lengthComputable ? event.loaded * 100 / event.total : 0); const gist = this._isSuccessCode(event.status) ? 'Success' : 'Error';
this._onProgressItem(item, progress); const method = '_on' + gist + 'Item';
}; if (this.uploaderService.options.chunkSize > 0) {
xhr.onload = () => { if ( (item.getCurrentChunk() +1) >= item.getTotalChunks()) {
let headers = this._parseHeaders(xhr.getAllResponseHeaders()); (this as any)[method](item, response, event.status, headers);
let response = this._transformResponse(xhr.response, headers); this._onCompleteItem(item, response, event.status, headers);
let gist = this._isSuccessCode(xhr.status) ? 'Success' : 'Error'; } else {
let method = '_on' + gist + 'Item'; this._onCompleteChunk(item, response, event.status, headers);
(this as any)[method](item, response, xhr.status, headers); }
this._onCompleteItem(item, response, xhr.status, headers); } else {
}; (this as any)[method](item, response, event.status, headers);
xhr.onerror = () => { this._onCompleteItem(item, response, event.status, headers);
let headers = this._parseHeaders(xhr.getAllResponseHeaders()); }
let response = this._transformResponse(xhr.response, headers);
this._onErrorItem(item, response, xhr.status, headers); }
this._onCompleteItem(item, response, xhr.status, headers); public onLoad(event: HttpResponse<any>, item: FileItem) {
}; this._onLoad(event, item);
xhr.onabort = () => { }
let headers = this._parseHeaders(xhr.getAllResponseHeaders());
let response = this._transformResponse(xhr.response, headers); protected _onError(error: any, item: FileItem) {
this._onCancelItem(item, response, xhr.status, headers); const headers: HttpHeaders = error.Headers
this._onCompleteItem(item, response, xhr.status, headers); const response = this._transformResponse(error.error, headers);
}; if (this.uploaderService.options.chunkSize > 0) {
xhr.open(item.method, item.url, true); this._onErrorChunk(item, response, error.status, headers);
xhr.withCredentials = item.withCredentials; } else {
if (this.options.headers) { this._onErrorItem(item, response, error.status, headers);
for (let header of this.options.headers) { this._onCompleteItem(item, response, error.status, headers);
xhr.setRequestHeader(header.name, header.value); }
} }
} public onError(error: HttpErrorResponse, item: FileItem) {
if (item.headers.length) { this._onError(error,item);
for (let header of item.headers) { }
xhr.setRequestHeader(header.name, header.value); protected _onAbort(error: HttpErrorResponse, item: FileItem) {
} this._onCancelItem(item);
} this._onCompleteItem(item);
if (this.authToken) { }
xhr.setRequestHeader(this.authTokenHeader, this.authToken);
} public onAbort(error: HttpErrorResponse, item: FileItem) {
xhr.onreadystatechange = function (): void { this._onAbort(error, item);
if (xhr.readyState === XMLHttpRequest.DONE) { }
that.response.emit(xhr.responseText);
} protected _uploadFile(item: FileItem): any {
}; this._onBeforeUploadItem(item);
if (this.options.formatDataFunctionIsAsync) { if (typeof item._file.size !== 'number') {
sendable.then( throw new TypeError('The file specified is no longer valid');
(result: any) => xhr.send(JSON.stringify(result)) }
); this.uploaderService.uploadFile(item, this.options);
} else { }
xhr.send(sendable);
} protected _getTotalProgress(value: number = 0): number {
this._render(); if (this.options.removeAfterUpload) {
} return value;
}
protected _getTotalProgress(value: number = 0): number { let notUploaded = this.getNotUploadedItems().length;
if (this.options.removeAfterUpload) { let uploaded = notUploaded ? this.queue.length - notUploaded : this.queue.length;
return value; let ratio = 100 / this.queue.length;
} let current = value * ratio / 100;
let notUploaded = this.getNotUploadedItems().length; return Math.round(uploaded * ratio + current);
let uploaded = notUploaded ? this.queue.length - notUploaded : this.queue.length; }
let ratio = 100 / this.queue.length;
let current = value * ratio / 100; protected _getFilters(filters: FilterFunction[] | string): FilterFunction[] {
return Math.round(uploaded * ratio + current); if (!filters) {
} return this.options.filters;
}
protected _getFilters(filters: FilterFunction[] | string): FilterFunction[] { if (Array.isArray(filters)) {
if (!filters) { return filters;
return this.options.filters; }
} if (typeof filters === 'string') {
if (Array.isArray(filters)) { let names = filters.match(/[^\s,]+/g);
return filters; return this.options.filters
} .filter((filter: any) => names.indexOf(filter.name) !== -1);
if (typeof filters === 'string') { }
let names = filters.match(/[^\s,]+/g); return this.options.filters;
return this.options.filters }
.filter((filter: any) => names.indexOf(filter.name) !== -1);
} protected _render(): any {
return this.options.filters; return void 0;
} }
protected _render(): any { protected _queueLimitFilter(): boolean {
return void 0; return this.options.queueLimit === undefined || this.queue.length < this.options.queueLimit;
} }
protected _queueLimitFilter(): boolean { protected _isValidFile(file: FileLikeObject, filters: FilterFunction[], options: FileUploaderOptions): boolean {
return this.options.queueLimit === undefined || this.queue.length < this.options.queueLimit; this._failFilterIndex = -1;
} return !filters.length ? true : filters.every((filter: FilterFunction) => {
this._failFilterIndex++;
protected async _isValidFile(file: FileLikeObject, filters: FilterFunction[], options: FileUploaderOptions, queueIndex: number): Promise<boolean> { return filter.fn.call(this, file, options);
this._failFilterIndex = -1; });
}
for (const filter of filters) {
this._failFilterIndex++; protected _isSuccessCode(status: number): boolean {
return (status >= 200 && status < 300) || status === 304;
if (!(await Promise.resolve(filter.fn.call(this, file, options, queueIndex)))) { }
return false;
} protected _transformResponse(response: string, headers: HttpHeaders): string {
} return response;
}
return true;
} protected _onWhenAddingFileFailed(item: FileLikeObject, filter: any, options: any): void {
this.onWhenAddingFileFailed(item, filter, options);
protected _isSuccessCode(status: number): boolean { }
return (status >= 200 && status < 300) || status === 304;
} protected _onAfterAddingFile(item: FileItem): void {
this.onAfterAddingFile(item);
protected _transformResponse(response: string, headers: ParsedResponseHeaders): string { }
return response;
} protected _onAfterAddingAll(items: any): void {
this.onAfterAddingAll(items);
protected _parseHeaders(headers: string): ParsedResponseHeaders { }
let parsed: any = {};
let key: any; protected _onBeforeUploadItem(item: FileItem): void {
let val: any; item._onBeforeUpload();
let i: any; this.onBeforeUploadItem(item);
if (!headers) { }
return parsed;
} public _onBuildItemForm(item: FileItem, form: any): void {
headers.split('\n').map((line: any) => { item._onBuildForm(form);
i = line.indexOf(':'); this.onBuildItemForm(item, form);
key = line.slice(0, i).trim().toLowerCase(); }
val = line.slice(i + 1).trim();
if (key) { protected _onProgressItem(item: FileItem, progress: any): void {
parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; const total = this._getTotalProgress(progress);
} this.progress = total;
}); item._onProgress(progress);
return parsed; this.onProgressItem(item, progress);
} this.onProgressAll(total);
this._render();
protected _onWhenAddingFileFailed(item: FileLikeObject, filter: any, options: any): void { }
this.onWhenAddingFileFailed(item, filter, options); protected _onErrorChunk(item: FileItem, response: string, status: number, headers: HttpHeaders): void {
} item._onErrorChunk(response, status, headers);
this.onErrorChunk(item, response, status, headers)
protected _onAfterAddingFile(item: FileItem): void { }
this.onAfterAddingFile(item); protected _onSuccessItem(item: FileItem, response: string, status: number, headers: HttpHeaders): void {
} item._onSuccess(response, status, headers);
this.onSuccessItem(item, response, status, headers);
protected _onAfterAddingAll(items: any): void { }
this.onAfterAddingAll(items);
} protected _onCancelItem(item: FileItem): void {
item._onCancel();
protected _onBeforeUploadItem(item: FileItem): void { this.onCancelItem(item);
item._onBeforeUpload(); }
this.onBeforeUploadItem(item); }
}
protected _onBuildItemForm(item: FileItem, form: any): void {
item._onBuildForm(form);
this.onBuildItemForm(item, form);
}
protected _onProgressItem(item: FileItem, progress: any): void {
let total = this._getTotalProgress(progress);
this.progress = total;
item._onProgress(progress);
this.onProgressItem(item, progress);
this.onProgressAll(total);
this._render();
}
protected _onSuccessItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): void {
item._onSuccess(response, status, headers);
this.onSuccessItem(item, response, status, headers);
}
protected _onCancelItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): void {
item._onCancel(response, status, headers);
this.onCancelItem(item, response, status, headers);
}
}

View File

@@ -0,0 +1,358 @@
import { HttpErrorResponse } from '@angular/common/http/src/response';
import { FileUploaderOptions, FileUploader } from './file-uploader.class';
import { FileItem } from './file-item.class';
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpRequest, HttpEventType } from '@angular/common/http';
import { Observable, of} from 'rxjs';
import { map } from 'rxjs/operators';
export interface UploaderLinksOptions {
downloadEntry: string;
updateEntry: string;
createEntry: string;
deleteEntry: string;
}
export interface UploaderServiceOptions {
createMethod: string;
updateMethod: string;
authorizationHeaderName?: string;
tokenPattern?: string;
token?: string;
chunkSize?: number;
totalChunkParamName?: string;
currentChunkParamName?: string;
fileParamName?: string;
idAttribute?: string;
}
@Injectable()
export class FileUploaderService {
public defaultLinks: UploaderLinksOptions = {
downloadEntry: '',
updateEntry: '',
createEntry: '',
deleteEntry: ''
};
public defaultOptions: UploaderServiceOptions = {
createMethod: 'POST',
updateMethod: 'POST',
authorizationHeaderName: 'Authorization',
tokenPattern: null,
token: null,
chunkSize: 0,
totalChunkParamName: 'total_chunks',
currentChunkParamName: 'current_chunk',
fileParamName: 'file',
idAttribute: 'id'
};
public additionalHeaders:any = {};
protected cancelError = 'UPLOAD CANCELED';
protected uploadSubscription: any = null;
public links: UploaderLinksOptions;
public options: UploaderServiceOptions;
private _uploader: FileUploader = null;
constructor(protected http: HttpClient) {
this.links = Object.assign({}, this.defaultLinks, this.links);
this.options = Object.assign({}, this.defaultOptions, this.options);
}
get uploader(): FileUploader {
return this._uploader;
}
set uploader(theUploader: FileUploader) {
this._uploader = theUploader;
}
public onBeforeUpload(
item: FileItem,
options: FileUploaderOptions
): Promise<any> {
const promise = new Promise((resolve, reject) => {
resolve(true);
});
return promise;
}
public uploadFile(item: FileItem, options: FileUploaderOptions): void {
this.onBeforeUpload(item, options).then(() => {
this._uploadFile(item, options);
});
}
public onBeforeGetDefaultHeaders(): Promise<any> {
const promise = new Promise((resolve, reject) => {
resolve(true);
});
return promise;
}
protected _getDefaultHeaders(): Promise<any> {
return new Promise((resolve, reject) => {
this.onBeforeGetDefaultHeaders().then(
result => {
const h: any = {};
if (this.options.tokenPattern && this.options.token) {
h[
this.options.authorizationHeaderName
] = this.options.tokenPattern.replace(
'#token#',
this.options.token
);
}
for (const key in this.additionalHeaders) {
if (this.additionalHeaders.hasOwnProperty(key)) {
h[key] = this.additionalHeaders[key];
}
}
resolve(h);
},
error => {
reject(error);
}
);
});
}
protected _getRequestHeaders(
item: FileItem,
options: FileUploaderOptions
): Promise<any> {
return new Promise((resolve, reject) => {
this._getDefaultHeaders().then(
h => {
if (options.headers) {
for (let header of options.headers) {
h[header.name] = header.value;
}
}
if (item.headers.length) {
for (let header of item.headers) {
h[header.name] = header.value;
}
}
resolve(h);
},
error => {
reject(error);
}
);
});
}
public buildPackageToSend(item: FileItem, options: FileUploaderOptions) {
let sendable: FormData = new FormData();
this.uploader._onBuildItemForm(item, sendable);
let file: any = null;
if (this.options.chunkSize > 0) {
file = item.getCurrentChunkFile();
} else {
file = item._file;
}
const appendFile = () =>
sendable.append(this.options.fileParamName, file, item.file.name);
if (!options.parametersBeforeFiles) {
appendFile();
}
// For AWS, Additional Parameters must come BEFORE Files
if (options.additionalParameter !== undefined) {
Object.keys(options.additionalParameter).forEach((key: string) => {
let paramVal = options.additionalParameter[key];
// Allow an additional parameter to include the filename
if (
typeof paramVal === 'string' &&
paramVal.indexOf('{{file_name}}') >= 0
) {
paramVal = paramVal.replace('{{file_name}}', item.file.name);
}
sendable.append(key, paramVal);
});
}
if (this.options.chunkSize > 0 && this.options.totalChunkParamName) {
sendable.append(
this.options.totalChunkParamName,
item.getTotalChunks().toString()
);
}
if (this.options.chunkSize > 0 && this.options.currentChunkParamName) {
sendable.append(
this.options.currentChunkParamName,
(item.getCurrentChunk() + 1).toString()
);
}
if (options.parametersBeforeFiles) {
appendFile();
}
return sendable;
}
protected _uploadFile(item: FileItem, options: FileUploaderOptions): void {
this._getRequestHeaders(item, options).then(
headers => {
let request_method = this.options.createMethod;
let link = this.links.createEntry;
item.setIsUploading(true);
if (this.options.chunkSize > 0) {
try {
item.getCurrentChunk();
} catch (err) {
item.createFileChunk(this.options.chunkSize);
}
request_method =
item.getCurrentChunk() > 0
? this.options.updateMethod
: this.options.createMethod;
link =
item.getCurrentChunk() > 0
? this.links.updateEntry
: this.links.createEntry;
}
if (item.getId()) {
link = link.replace('#id#', item.getId());
}
const data = this.buildPackageToSend(item, options);
const request = new HttpRequest(request_method, link, data, {
headers: new HttpHeaders(headers),
reportProgress: true,
withCredentials: item.withCredentials,
});
this.uploadSubscription = this.http.request(request).subscribe(
(event: any) => {
this.getEventMessage(event, item);
},
(error: any) => {
if (this.cancelError === error) {
this.uploader.onAbort(error, item);
} else {
this.uploader.onError(error, item);
}
}
);
},
error => {}
);
}
public stopUpload() {
if (this.uploadSubscription && this.uploadSubscription.unsubscribe) {
this.uploadSubscription.error(this.cancelError);
}
}
private getEventMessage(event: any, item: FileItem) {
switch (event.type) {
case HttpEventType.ResponseHeader:
break;
case HttpEventType.Sent:
this.uploader.onStart(event, item);
break;
case HttpEventType.UploadProgress:
this.uploader.onProgress(event, item);
break;
case HttpEventType.Response:
if (this.options.chunkSize > 0) {
if (item.getCurrentChunk() === 0) {
const response = event.body;
if (response[this.options.idAttribute]) {
item.setId(response[this.options.idAttribute]);
}
}
}
this.uploader.onLoad(event, item);
break;
default:
break;
}
}
private handleError(item: FileItem) {
const userMessage = `${item.file.name} upload failed.`;
return (error: HttpErrorResponse) => {
this.uploader.onError(error, item);
const message =
error.error instanceof Error
? error.error.message
: `server returned code ${error.status} with body "${error.error}"`;
return of (userMessage);
};
}
public deleteEntry(
item: FileItem,
options = {},
skipConfirmation = false
): Observable <any> {
if (item.getId() && this.links['deleteEntry']) {
let link = this.links['deleteEntry'].replace(/#id#/g, item.getId());
let confirmation = false;
if (skipConfirmation) {
confirmation = true;
} else {
confirmation = confirm('Are you sure you want to delete this entry?');
}
if (confirmation) {
return this.delete(link, options)
} else {
return of(false);
}
} else {
return of(false);
}
}
protected delete(url: string, options = {}): Observable<any> {
return new Observable((observe:any) => {
this._getDefaultHeaders().then(
function(headers: any) {
return this.http
.delete(url, { headers: new HttpHeaders(headers) })
.subscribe(
(response: Response) => {
observe.next(response);
},
(error: any) => {
observe.error(error);
}
);
}.bind(this),
error => {
observe.error(error);
}
);
});
}
/*
HTTP General methos only bellow
*/
protected get(url: string): Observable<any> {
return new Observable(observe => {
this._getDefaultHeaders().then(
function(headers:any) {
return this.http
.get(url, { headers: new HttpHeaders(headers) })
.subscribe(
(response: Response) => {
observe.next(response);
},
(error: any) => {
observe.error(error);
}
);
}.bind(this),
error => {
observe.error(error);
}
);
});
}
public addHeader(name:string = null, value:any = null) {
this.additionalHeaders[name] = value;
}
public removeHeader(name:string = null) {
if (this.additionalHeaders.hasOwnProperty(name)) {
delete this.additionalHeaders[name];
}
}
}

View File

@@ -3,5 +3,6 @@ export * from './file-upload/file-drop.directive';
export * from './file-upload/file-uploader.class'; export * from './file-upload/file-uploader.class';
export * from './file-upload/file-item.class'; export * from './file-upload/file-item.class';
export * from './file-upload/file-like-object.class'; export * from './file-upload/file-like-object.class';
export * from './file-upload/file-uploader.service';
export { FileUploadModule } from './file-upload/file-upload.module'; export { FileUploadModule } from './file-upload/file-upload.module';

View File

@@ -1,5 +1,5 @@
{ {
"name": "ng2-file-upload", "name": "ng2-chunk-file-upload",
"version": "1.3.0", "version": "1.3.0",
"peerDependencies": { "peerDependencies": {
"@angular/common": "*", "@angular/common": "*",

View File

@@ -28,7 +28,7 @@
], ],
"files": [ "files": [
"../scripts/typings.d.ts", "../scripts/typings.d.ts",
"./ng2-file-upload.ts", "./ng2-chunk-file-upload.ts",
"./index.ts" "./index.ts"
], ],
"angularCompilerOptions": { "angularCompilerOptions": {

24
tsconfig.json Normal file
View File

@@ -0,0 +1,24 @@
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2017",
"dom"
],
"plugins": [
{
"name": "tslint-language-service"
}
]
}
}

View File

@@ -1,12 +1,136 @@
{ {
"extends": "tslint-config-valorsoft", "rulesDirectory": [
"rulesDirectory": "./node_modules/codelyzer", "node_modules/codelyzer"
"rules": { ],
"no-forward-ref": false, "rules": {
"no-null-keyword": false, "trailing-comma": [
"only-arrow-functions": false, true,
"no-access-missing-member": false, {
"directive-selector": false, "multiline": "always",
"component-selector": false "singleline": "never"
} }
} ],
"arrow-return-shorthand": true,
"callable-types": true,
"class-name": true,
"comment-format": [
true,
"check-space"
],
"eofline": true,
"forin": true,
"import-blacklist": [
true
],
"import-spacing": true,
"indent": [
true,
"tabs",
4
],
"interface-over-type-literal": true,
"label-position": true,
"max-line-length": [
true,
180
],
"member-access": false,
"no-arg": true,
"no-console": [
true,
"debug",
"log",
"time",
"timeEnd",
"trace"
],
"no-construct": true,
"no-debugger": true,
"no-duplicate-super": true,
"no-empty": false,
"no-empty-interface": true,
"no-eval": true,
"no-misused-new": true,
"no-non-null-assertion": true,
"no-shadowed-variable": true,
"no-string-literal": false,
"no-string-throw": true,
"no-switch-case-fall-through": true,
"no-trailing-whitespace": true,
"no-unnecessary-initializer": true,
"no-use-before-declare": true,
"no-var-keyword": true,
"object-literal-sort-keys": false,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-whitespace"
],
"prefer-const": true,
"quotemark": [
true,
"single"
],
"radix": true,
"semicolon": [
true
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"typeof-compare": true,
"unified-signatures": true,
"variable-name": false,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
],
"directive-selector": [
true,
"attribute",
"ngx",
"camelCase"
],
"component-selector": [
true,
"element",
"ngx",
"kebab-case"
],
"ban": [
true,
"eval",
"fit",
"fdescribe",
{
"name": "$",
"message": "please don't"
}
],
"use-input-property-decorator": true,
"use-output-property-decorator": true,
"no-output-rename": true,
"use-life-cycle-interface": true,
"use-pipe-transform-interface": true,
"component-class-suffix": true,
"directive-class-suffix": true,
"no-unused-variable": true
}
}