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
95 changed files with 15622 additions and 25935 deletions

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,60 +0,0 @@
{
"root": true,
"ignorePatterns": [
"**/*"
],
"plugins": [
"@nrwl/nx"
],
"overrides": [
{
"files": [
"*.ts",
"*.tsx",
"*.js",
"*.jsx"
],
"rules": {
"@nrwl/nx/enforce-module-boundaries": [
"error",
{
"enforceBuildableLibDependency": true,
"allow": [],
"depConstraints": [
{
"sourceTag": "*",
"onlyDependOnLibsWithTags": [
"*"
]
}
]
}
]
}
},
{
"files": [
"*.ts",
"*.tsx"
],
"extends": [
"plugin:@nrwl/nx/typescript"
],
"parserOptions": { "project": "./tsconfig.*?.json" },
"rules": {
"semi": "off",
"@typescript-eslint/semi": ["error"]
}
},
{
"files": [
"*.js",
"*.jsx"
],
"extends": [
"plugin:@nrwl/nx/javascript"
],
"rules": {}
}
]
}

View File

@@ -1,5 +0,0 @@
{
"projects": {
"default": "ngx-file-upload"
}
}

View File

@@ -1,121 +0,0 @@
name: on-release
on:
push:
tags:
- v*
env:
NX_BRANCH: ${{ github.event.number }}
NX_RUN_GROUP: ${{ github.run_id }}
NX_CLOUD_AUTH_TOKEN: ${{ secrets.NX_CLOUD_AUTH_TOKEN }}
MOZ_HEADLESS: 1
CONVENTIONAL_GITHUB_RELEASER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
# one run
one_run:
runs-on: ubuntu-latest
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.9.0
with:
access_token: ${{ secrets.GITHUB_TOKEN }}
# install dependencies
install:
runs-on: ubuntu-latest
needs: one_run
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/cache@v2.1.4
id: cache
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- run: npm ci
if: steps.cache.outputs.cache-hit != 'true'
# build ng2-file-upload
build:
needs: install
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/cache@v2.1.4
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- uses: actions/cache@v2.1.4
with:
path: |
dist
key: dist-${{ github.run_id }}
- run: npx ng build --prod
# update release notes in github
update_release_draft:
needs: install
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/cache@v2.1.4
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- run: npx conventional-github-releaser -p angular
# update gh_pages
gh_pages_deploy:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/checkout@v2.3.4
with:
ref: 'gh-pages'
path: 'gh-pages'
- uses: actions/cache@v2.1.4
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- uses: actions/cache@v2.1.4
with:
path: |
dist
key: dist-${{ github.run_id }}
- run: |
cd gh-pages
git config user.email gh-actions-${GITHUB_ACTOR}@github.com
git config user.name $GITHUB_ACTOR
git add -A
git commit -am "ci: gh-pages update"
continue-on-error: true
- name: push to gh-pages
uses: ad-m/github-push-action@v0.6.0
continue-on-error: true
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: 'gh-pages'
directory: 'gh-pages'
# publish to npm
npm_publish:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/cache@v2.1.4
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- uses: actions/cache@v2.1.4
with:
path: |
dist
key: dist-${{ github.run_id }}
- uses: JS-DevTools/npm-publish@v1
with:
package: "dist/libs/ng2-file-upload/package.json"
token: ${{ secrets.NPM_TOKEN }}

View File

@@ -1,113 +0,0 @@
name: on-pull-request-or-push
on:
pull_request:
push:
branches:
- development
env:
NX_BRANCH: ${{ github.event.number }}
NX_RUN_GROUP: ${{ github.run_id }}
NX_CLOUD_AUTH_TOKEN: ${{ secrets.NX_CLOUD_AUTH_TOKEN }}
MOZ_HEALESS: 1
SAUCE_USERNAME_PR: valorkinpr
FIREBASE_CHANNEL: ${{ fromJSON('["", "live"]')[!github.base_ref] }}
CACHE_NODE_MODULES_PATH: |
~/.npm
node_modules
CACHE_DIST_PATH: |
dist
jobs:
# one run
one_run:
runs-on: ubuntu-latest
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.9.0
with:
access_token: ${{ secrets.GITHUB_TOKEN }}
# install dependencies
install:
runs-on: ubuntu-latest
needs: one_run
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/cache@v2.1.4
id: cache
with:
path: ${{ env.CACHE_NODE_MODULES_PATH }}
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- run: npm ci
if: steps.cache.outputs.cache-hit != 'true'
# build ng2-file-upload
build:
needs: install
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/cache@v2.1.4
with:
path: ${{ env.CACHE_NODE_MODULES_PATH }}
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- uses: actions/cache@v2.1.4
with:
path: ${{ env.CACHE_DIST_PATH }}
key: dist-${{ github.run_id }}
- run: npx ng build --prod
# run unit tests
unit_tests_with_coverage:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: ${{ env.CACHE_NODE_MODULES_PATH }}
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- uses: actions/cache@v2
with:
path: ${{ env.CACHE_DIST_PATH }}
key: dist-${{ github.run_id }}
- run: npm run test-coverage
continue-on-error: true
# run linting
linting:
runs-on: ubuntu-latest
needs: install
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: ${{ env.CACHE_NODE_MODULES_PATH }}
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- run: npm run lint
# firebase preview
build_and_preview:
runs-on: ubuntu-latest
needs: build
outputs:
output_url: ${{ steps.firebase_hosting_preview.outputs.details_url }}
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: ${{ env.CACHE_DIST_PATH }}
key: dist-${{ github.run_id }}
- uses: FirebaseExtended/action-hosting-deploy@v0
continue-on-error: true
id: firebase_hosting_preview
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_NGX_FILE_UPLOAD }}'
projectId: ngx-file-upload
channelId: ${{ env.FIREBASE_CHANNEL }}
expires: 7d

View File

@@ -1,13 +1,11 @@
language: node_js
node_js:
- "10"
services:
- xvfb
- "6"
before_install:
- export CHROME_BIN=chromium-browser
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
script:
- npm run pretest

View File

@@ -1,160 +1,108 @@
# [2.0.0-0](https://github.com/valor-software/ng2-file-upload/compare/v1.2.0...v2.0.0-0) (2021-09-03)
### Bug Fixes
* **ci:** fix xvfb service issue ([33ac156](https://github.com/valor-software/ng2-file-upload/commit/33ac156208bfcf57851210f037719107e1ca9eb9))
* **typo:** fix grammatical mistake in readme ([#1119](https://github.com/valor-software/ng2-file-upload/issues/1119)) ([8171bc8](https://github.com/valor-software/ng2-file-upload/commit/8171bc831b69692d04b650be19ff82f04ff56662))
### 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/7704e0e970276ebcd8bfefe34bf153f82108a11e))
# [1.3.0](https://github.com/valor-software/ng2-file-upload/compare/v1.2.0...v1.3.0) (2021-08-31)
### Bug Fixes
* **ci:** fix xvfb service issue ([33ac156](https://github.com/valor-software/ng2-file-upload/commit/33ac156208bfcf57851210f037719107e1ca9eb9))
* **style:** delete extra rule ([b5917b9](https://github.com/valor-software/ng2-file-upload/commit/b5917b9fa77e63c4c1b06598abc817b8033730c3))
* **typo:** fix grammatical mistake in readme ([#1119](https://github.com/valor-software/ng2-file-upload/issues/1119)) ([8171bc8](https://github.com/valor-software/ng2-file-upload/commit/8171bc831b69692d04b650be19ff82f04ff56662))
### Features
* **bump:** added strict mode, doesn't build in dist, should be resolved ([69cd64d](https://github.com/valor-software/ng2-file-upload/commit/69cd64dc287c9bdd1c35af1062e27ce32a47e977))
* **core:** added nx ([de738f7](https://github.com/valor-software/ng2-file-upload/commit/de738f7c63d7f37e07019bc596c02e9f4320f563))
* **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/7704e0e970276ebcd8bfefe34bf153f82108a11e))
* **upgrade:** updated up to angular 11 tests are failed ([ce9dc20](https://github.com/valor-software/ng2-file-upload/commit/ce9dc20056cc6c7cd58e502af05d7d97043c8f3a))
# [1.3.0](https://github.com/valor-software/ng2-file-upload/compare/v1.2.0...v1.3.0) (2021-08-31)
### Bug Fixes
* **ci:** fix xvfb service issue ([33ac156](https://github.com/valor-software/ng2-file-upload/commit/33ac156208bfcf57851210f037719107e1ca9eb9))
* **style:** delete extra rule ([b5917b9](https://github.com/valor-software/ng2-file-upload/commit/b5917b9fa77e63c4c1b06598abc817b8033730c3))
* **typo:** fix grammatical mistake in readme ([#1119](https://github.com/valor-software/ng2-file-upload/issues/1119)) ([8171bc8](https://github.com/valor-software/ng2-file-upload/commit/8171bc831b69692d04b650be19ff82f04ff56662))
### Features
* **bump:** added strict mode, doesn't build in dist, should be resolved ([69cd64d](https://github.com/valor-software/ng2-file-upload/commit/69cd64dc287c9bdd1c35af1062e27ce32a47e977))
* **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/7704e0e970276ebcd8bfefe34bf153f82108a11e))
* **upgrade:** updated up to angular 11 tests are failed ([ce9dc20](https://github.com/valor-software/ng2-file-upload/commit/ce9dc20056cc6c7cd58e502af05d7d97043c8f3a))
<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
* **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 file type .zip ([#911](https://github.com/valor-software/ng2-file-upload/pull/911))
* **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-chunk-file-upload/pull/911))
### Bug Fixes
* **file-uploader** Update: setOptions ([#904](https://github.com/valor-software/ng2-file-upload/pull/904))
* **docs** Fix correct path for isHTML5 option ([#844](https://github.com/valor-software/ng2-file-upload/pull/844))
* **docs** Added onFileDrop() event to documentation ([#857](https://github.com/valor-software/ng2-file-upload/pull/857))
* **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-chunk-file-upload/pull/844))
* **docs** Added onFileDrop() event to documentation ([#857](https://github.com/valor-software/ng2-chunk-file-upload/pull/857))
<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
* **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>
# [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
* **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
* **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))
* **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))
* **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))
* **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-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-chunk-file-upload/issues/574)) ([3cc6a99](https://github.com/valor-software/ng2-chunk-file-upload/commit/3cc6a99))
<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
* **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
* **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)
* **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))
* **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-chunk-file-upload/issues/213)) ([282295c](https://github.com/valor-software/ng2-chunk-file-upload/commit/282295c))
<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
* **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>
## [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
* **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))
* **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))
* **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-chunk-file-upload/issues/221)) ([db77e89](https://github.com/valor-software/ng2-chunk-file-upload/commit/db77e89))
### 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))
* **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:** updated to typescript 2 ([4fef496](https://github.com/valor-software/ng2-file-upload/commit/4fef496))
* **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-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-chunk-file-upload/commit/4fef496))
<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
* **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))
* **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))
* **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-chunk-file-upload/issues/221)) ([db77e89](https://github.com/valor-software/ng2-chunk-file-upload/commit/db77e89))
### 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))
* **package:** updated to typescript 2 ([4fef496](https://github.com/valor-software/ng2-file-upload/commit/4fef496))
* **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-chunk-file-upload/commit/4fef496))
<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)
@@ -164,17 +112,17 @@
### 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
* **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
* **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

110
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)
Easy to use Angular2 directives for files upload ([demo](http://valor-software.github.io/ng2-file-upload/))
# 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-chunk-file-upload/))
[![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)
[![Dependency Status](https://david-dm.org/valor-software/ng2-file-upload.svg)](https://david-dm.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-chunk-file-upload.svg)](https://david-dm.org/valor-software/ng2-chunk-file-upload)
## 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.
3. More information regarding using of ***ng2-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).
3. More information regarding using of ***ng2-chunk-file-upload*** is located in
[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.
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`:
@@ -33,7 +33,7 @@ Easy to use Angular2 directives for files upload ([demo](http://valor-software.g
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:
@@ -47,7 +47,7 @@ Easy to use Angular2 directives for files upload ([demo](http://valor-software.g
### 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
- `onFileSelected` - fires when files are selected and added to the uploader queue
@@ -56,34 +56,100 @@ Easy to use Angular2 directives for files upload ([demo](http://valor-software.g
### 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:
1. `url` - URL of File Uploader's route
2. `authToken` - Auth token that will be applied as 'Authorization' header during file send.
3. `disableMultipart` - If 'true', disable using a multipart form for file upload and instead stream the file. Some APIs (e.g. Amazon S3) may expect the file to be streamed rather than sent via a form. Defaults to false.
4. `itemAlias` - item alias (form name redefinition)
4. `itemAlias` - item alias (form name redefenition)
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.
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
- `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
[html demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.html)
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-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)"`
# Troubleshooting
Please follow these 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.
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
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)

View File

@@ -2,89 +2,25 @@
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"defaultProject": "ng2-file-upload-demo",
"projects": {
"ng2-file-upload": {
"root": "libs/ng2-file-upload",
"sourceRoot": "libs/ng2-file-upload/src",
"projectType": "library",
"architect": {
"build": {
"builder": "@nrwl/angular:package",
"outputs": [
"dist/libs/ng2-file-upload"
],
"options": {
"tsConfig": "libs/ng2-file-upload/tsconfig.lib.json",
"project": "libs/ng2-file-upload/ng-package.json"
},
"configurations": {
"production": {
"tsConfig": "libs/ng2-file-upload/tsconfig.lib.prod.json"
}
}
},
"lint": {
"builder": "@nrwl/linter:eslint",
"options": {
"lintFilePatterns": [
"libs/ng2-file-upload/**/*.ts"
]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"outputs": [
"coverage/libs/ng2-file-upload"
],
"options": {
"jestConfig": "libs/ng2-file-upload/jest.config.js",
"passWithNoTests": true
}
},
"version": {
"builder": "@nrwl/workspace:run-commands",
"outputs": [
],
"options": {
"commands": [
"ts-node ./scripts/set-version.ts",
"conventional-changelog -i CHANGELOG.md -s -p angular",
"git add -A",
"git commit -am \"chore(changelog): update [skip ci] \""
],
"parallel": false
},
"configurations": {
"production": {}
}
}
}
},
"ng2-file-upload-demo": {
"root": "apps/demo",
"sourceRoot": "apps/demo/src",
"ng2-chunk-file-upload": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/apps/demo",
"index": "apps/demo/src/index.html",
"main": "apps/demo/src/main.ts",
"tsConfig": "apps/demo/tsconfig.json",
"outputPath": "demo/dist",
"index": "demo/src/index.html",
"main": "demo/src/main.ts",
"tsConfig": "demo/src/tsconfig.json",
"assets": [
"apps/demo/src/assets"
"demo/src/assets"
],
"styles": [],
"scripts": []
},
"dependsOn": [
{
"target": "build",
"projects": "dependencies"
}
],
"configurations": {
"production": {
"optimization": true,
@@ -98,8 +34,8 @@
"buildOptimizer": true,
"fileReplacements": [
{
"replace": "apps/demo/src/environments/environment.ts",
"with": "apps/demo/src/environments/environment.prod.ts"
"replace": "demo/src/environments/environment.ts",
"with": "demo/src/environments/environment.prod.ts"
}
]
}
@@ -108,26 +44,64 @@
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "ng2-file-upload-demo:build"
"browserTarget": "ng2-chunk-file-upload:build"
},
"configurations": {
"production": {
"browserTarget": "ng2-file-upload-demo:build:production"
"browserTarget": "ng2-chunk-file-upload:build:production"
}
}
},
"lint": {
"builder": "@nrwl/linter:eslint",
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"lintFilePatterns": [
"apps/demo/**/*.ts"
"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-file-upload-demo",
"defaultProject": "ng2-chunk-file-upload",
"schematics": {
"@schematics/angular:component": {
"prefix": "",
@@ -137,4 +111,4 @@
"prefix": ""
}
}
}
}

View File

@@ -1,21 +0,0 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts"],
"extends": [
"plugin:@nrwl/nx/angular",
"plugin:@angular-eslint/template/process-inline-templates"
],
"parserOptions": { "project": ["src/accordion/tsconfig.*?.json"] },
"rules": {
}
},
{
"files": ["*.html"],
"extends": ["plugin:@nrwl/nx/angular-template"],
"rules": {}
}
]
}

View File

@@ -1,12 +0,0 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# You can see what browsers were selected by your queries by running:
# npx browserslist
> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.

View File

@@ -1,4 +0,0 @@
{
"port": 4200,
"server": { "baseDir": "./dist/apps/demo" }
}

View File

@@ -1,43 +0,0 @@
import { Component } from '@angular/core';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const gettingStarted = require('html-loader!markdown-loader!../getting-started.md');
@Component({
selector: 'app',
template: `
<main class="bd-pageheader">
<div class="container">
<h1>ng2-file-upload</h1>
<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>
<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"><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>
</div>
</div>
</main>
<div class="container">
<section id="getting-started" [innerHtml]="gettingStarted"></section>
<file-upload-section class="col-md-12"></file-upload-section>
</div>
<footer class="footer">
<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>
</div>
</footer>
`
})
export class AppComponent {
public gettingStarted:string = gettingStarted;
public ngAfterContentInit(): any {
setTimeout(()=>{
if (typeof PR !== 'undefined') {
// google code-prettify
PR.prettyPrint();
}
}, 150);
}
}

View File

@@ -1,32 +0,0 @@
import { Component } from '@angular/core';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const doc = require('html-loader!markdown-loader!../../doc.md');
const tabDesc: Array<any> = [
{
heading: 'Simple',
// eslint-disable-next-line @typescript-eslint/no-var-requires
ts: require('!!raw-loader!./file-upload/simple-demo.ts').default,
// eslint-disable-next-line @typescript-eslint/no-var-requires
html: require('!!raw-loader!./file-upload/simple-demo.html').default,
// eslint-disable-next-line @typescript-eslint/no-var-requires
js: require('!!raw-loader!./file-upload/file-catcher.js').default
}
];
@Component({
selector: 'file-upload-section',
templateUrl: './file-upload-section.html'
})
export class FileUploadSectionComponent {
name = 'File Upload';
currentHeading = 'Simple';
doc = doc;
tabs: any = tabDesc;
select(e: any): void {
if (e.heading) {
this.currentHeading = e.heading;
}
}
}

View File

@@ -1,17 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["node"],
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"angularCompilerOptions": {
"strictInjectionParameters": true,
"strictTemplates": true,
"fullTemplateTypeCheck": true
},
"files": ["src/main.ts"]
}

View File

@@ -1,7 +0,0 @@
{
"extends": "./tsconfig.json",
"include": ["**/*.ts"],
"compilerOptions": {
"types": ["jest", "node"]
}
}

View File

@@ -1,20 +0,0 @@
{
"extends": "../../tsconfig.base.json",
"files": [
"./src/main.ts",
"../../scripts/polyfills.ts"
],
"include": ["./src/typings.d.ts"],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.spec.json"
},
{
"path": "./tsconfig.editor.json"
}
],
"exclude": ["**/*.spec.ts"]
}

View File

@@ -1,69 +0,0 @@
/**
* This file decorates the Angular CLI with the Nx CLI to enable features such as computation caching
* and faster execution of tasks.
*
* It does this by:
*
* - Patching the Angular CLI to warn you in case you accidentally use the undecorated ng command.
* - Symlinking the ng to nx command, so all commands run through the Nx CLI
* - Updating the package.json postinstall script to give you control over this script
*
* The Nx CLI decorates the Angular CLI, so the Nx CLI is fully compatible with it.
* Every command you run should work the same when using the Nx CLI, except faster.
*
* Because of symlinking you can still type `ng build/test/lint` in the terminal. The ng command, in this case,
* will point to nx, which will perform optimizations before invoking ng. So the Angular CLI is always invoked.
* The Nx CLI simply does some optimizations before invoking the Angular CLI.
*
* To opt out of this patch:
* - Replace occurrences of nx with ng in your package.json
* - Remove the script from your postinstall script in your package.json
* - Delete and reinstall your node_modules
*/
const fs = require('fs');
const os = require('os');
const cp = require('child_process');
const isWindows = os.platform() === 'win32';
let output;
try {
output = require('@nrwl/workspace').output;
} catch (e) {
console.warn('Angular CLI could not be decorated to enable computation caching. Please ensure @nrwl/workspace is installed.');
process.exit(0);
}
/**
* Symlink of ng to nx, so you can keep using `ng build/test/lint` and still
* invoke the Nx CLI and get the benefits of computation caching.
*/
function symlinkNgCLItoNxCLI() {
try {
const ngPath = './node_modules/.bin/ng';
const nxPath = './node_modules/.bin/nx';
if (isWindows) {
/**
* This is the most reliable way to create symlink-like behavior on Windows.
* Such that it works in all shells and works with npx.
*/
['', '.cmd', '.ps1'].forEach(ext => {
if (fs.existsSync(nxPath + ext)) fs.writeFileSync(ngPath + ext, fs.readFileSync(nxPath + ext));
});
} else {
// If unix-based, symlink
cp.execSync(`ln -sf ./nx ${ngPath}`);
}
}
catch(e) {
output.error({ title: 'Unable to create a symlink from the Angular CLI to the Nx CLI:' + e.message });
throw e;
}
}
try {
symlinkNgCLItoNxCLI();
require('@nrwl/cli/lib/decorate-cli').decorateCli();
output.log({ title: 'Angular CLI has been decorated to enable computation caching.' });
} catch(e) {
output.error({ title: 'Decoration of the Angular CLI did not complete successfully' });
}

4
demo/bs-config.json Normal file
View File

@@ -0,0 +1,4 @@
{
"port": 4200,
"server": { "baseDir": "./demo/dist" }
}

View File

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

View File

@@ -4,16 +4,24 @@ import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
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 { FileUploadSectionComponent } from './components/file-upload-section';
import { SimpleDemoComponent } from './components/file-upload/simple-demo';
import { HttpModule } from '@angular/http';
@NgModule({
imports: [BrowserModule, CommonModule, FileUploadModule, TabsModule.forRoot(), FormsModule],
declarations: [AppComponent, FileUploadSectionComponent, SimpleDemoComponent],
bootstrap: [AppComponent]
imports: [
HttpModule,
BrowserModule,
CommonModule,
FileUploadModule,
TabsModule.forRoot(),
FormsModule,
],
declarations: [AppComponent, FileUploadSectionComponent, SimpleDemoComponent],
bootstrap: [AppComponent],
})
export class AppModule {
}
export class AppModule {}

View File

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

View File

@@ -1,5 +1,5 @@
import { Component } from '@angular/core';
import { FileUploader } from 'ng2-file-upload';
import { FileUploader } from 'ng2-chunk-file-upload';
// const URL = '/api/';
const URL = 'https://evening-anchorage-3159.herokuapp.com/api/';
@@ -10,18 +10,18 @@ const URL = 'https://evening-anchorage-3159.herokuapp.com/api/';
})
export class SimpleDemoComponent {
uploader: FileUploader;
hasBaseDropZoneOver: boolean;
hasAnotherDropZoneOver: boolean;
response: string;
uploader:FileUploader;
hasBaseDropZoneOver:boolean;
hasAnotherDropZoneOver:boolean;
response:string;
constructor() {
constructor (){
this.uploader = new FileUploader({
url: URL,
disableMultipart: true, // 'DisableMultipart' must be 'true' for formatDataFunction to be called.
formatDataFunctionIsAsync: true,
formatDataFunction: async item => {
return new Promise((resolve, reject) => {
formatDataFunction: async (item) => {
return new Promise( (resolve, reject) => {
resolve({
name: item._file.name,
length: item._file.size,
@@ -37,14 +37,14 @@ export class SimpleDemoComponent {
this.response = '';
this.uploader.response.subscribe(res => this.response = res );
this.uploader.response.subscribe( res => this.response = res );
}
fileOverBase(e: any): void {
public fileOverBase(e:any):void {
this.hasBaseDropZoneOver = e;
}
fileOverAnother(e: any): void {
public fileOverAnother(e:any):void {
this.hasAnotherDropZoneOver = e;
}
}

View File

@@ -123,14 +123,6 @@ section {
background-color: #eee;
}
simple-demo {
max-width: 100%;
}
simple-demo >.container {
max-width: 100%;
}
@media (min-width: 992px) {
.bd-pageheader h1, .bd-pageheader p {
margin-right: 380px;

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

@@ -1,6 +1,6 @@
### Usage
```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
@@ -18,7 +18,7 @@ import { FileSelectDirective, FileDropDirective, FileUploader } from 'ng2-file-u
### 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:
@@ -37,11 +37,11 @@ import { FileSelectDirective, FileDropDirective, FileUploader } from 'ng2-file-u
### 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
- `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
[html demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.html)
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-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)"`

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

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

View File

@@ -9,10 +9,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<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 rel="stylesheet" crossorigin="anonymous" 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">
<link rel="stylesheet" href="assets/css/style.css">
<link rel="stylesheet" href="assets/css/prettify-angulario.css">
<style media="screen">

View File

@@ -1,4 +1,4 @@
import '../../../scripts/polyfills.ts';
import './polyfills.ts';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';

21
demo/src/polyfills.ts Normal file
View File

@@ -0,0 +1,21 @@
// This file includes polyfills needed by Angular 2 and is loaded before
// the app. You can add your own extra polyfills to this file.
import 'ts-helpers';
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/set';
import 'core-js/es6/reflect';
import 'core-js/es7/reflect';
import 'zone.js/dist/zone';
import 'classlist-polyfill';

17
demo/src/tsconfig.json Normal file
View File

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

16
demo/src/typings.d.ts vendored Normal file
View File

@@ -0,0 +1,16 @@
// Typings reference file, you can add your own global typings here
// https://www.typescriptlang.org/docs/handbook/writing-declaration-files.html
// tslint:disable
declare const System: any;
declare const ENV:string;
// google code-prettify
declare const PR:any;
// declare const require:any;
// declare const global:any;
declare module jasmine {
interface Matchers {
toHaveCssClass(expected: any): boolean;
}
}

View File

@@ -1,16 +0,0 @@
{
"hosting": {
"public": "./dist/apps/demo/",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "index.html"
}
]
}
}

View File

@@ -1,5 +0,0 @@
module.exports = {
projects: [
'<rootDir>/libs/ng2-file-upload'
]
};

View File

@@ -1,7 +0,0 @@
const nxPreset = require('@nrwl/jest/preset');
module.exports = {
...nxPreset,
...{
coverageReporters: ['text-summary', 'json', 'lcov']
}
}

83
karma.conf.js Normal file
View File

@@ -0,0 +1,83 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/0.13/config/configuration-file.html
const customLaunchers = require('./scripts/sauce-browsers').customLaunchers;
module.exports = function (config) {
const configuration = {
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
],
files: [
{pattern: './scripts/test.ts', watched: false}
],
preprocessors: {
'./scripts/test.ts': ['@angular-devkit/build-angular']
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: false
},
angularCli: {
config: './angular-cli.json',
environment: 'dev'
},
reporters: config.angularCli && config.angularCli.codeCoverage
? ['dots', 'coverage-istanbul']
: ['dots'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
customLaunchers: {
Chrome_travis_ci: {
base: 'Chrome',
flags: ['--no-sandbox']
}
},
mime: { 'text/x-typescript': ['ts','tsx'] },
client: { captureConsole: true }
};
if (process.env.TRAVIS) {
configuration.browsers = ['Chrome_travis_ci'];
}
if (process.env.SAUCE) {
if (!process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY) {
console.log('Make sure the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables are set.');
process.exit(1);
}
configuration.plugins.push(require('karma-sauce-launcher'));
configuration.reporters.push('saucelabs');
configuration.sauceLabs = {
verbose: true,
testName: 'ng2-bootstrap unit tests',
recordScreenshots: false,
username: process.env.SAUCE_USERNAME,
accessKey: process.env.SAUCE_ACCESS_KEY,
connectOptions: {
port: 5757,
logfile: 'sauce_connect.log'
},
public: 'public'
};
configuration.captureTimeout = 0;
configuration.customLaunchers = customLaunchers();
configuration.browsers = Object.keys(configuration.customLaunchers);
configuration.concurrency = 3;
configuration.browserDisconnectTolerance = 2;
configuration.browserNoActivityTimeout = 20000;
configuration.browserDisconnectTimeout = 5000;
}
config.set(configuration);
};

View File

@@ -1,21 +0,0 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts"],
"extends": [
"plugin:@nrwl/nx/angular",
"plugin:@angular-eslint/template/process-inline-templates"
],
"parserOptions": { "project": ["src/accordion/tsconfig.*?.json"] },
"rules": {
}
},
{
"files": ["*.html"],
"extends": ["plugin:@nrwl/nx/angular-template"],
"rules": {}
}
]
}

View File

@@ -1,10 +0,0 @@
# libs-ng2-file-upload
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test libs-ng2-file-upload` to execute the unit tests via [Jest](https://jestjs.io).

View File

@@ -1,89 +0,0 @@
import { Directive, EventEmitter, ElementRef, HostListener, Input, Output } from '@angular/core';
import { FileUploader, FileUploaderOptions } from './file-uploader.class';
@Directive({ selector: '[ng2FileDrop]' })
export class FileDropDirective {
@Input() uploader?: FileUploader;
@Output() fileOver: EventEmitter<any> = new EventEmitter();
// eslint-disable-next-line @angular-eslint/no-output-on-prefix
@Output() onFileDrop: EventEmitter<File[]> = new EventEmitter<File[]>();
protected element: ElementRef;
constructor(element: ElementRef) {
this.element = element;
}
getOptions(): FileUploaderOptions | void {
return this.uploader?.options;
}
getFilters(): string {
return '';
}
@HostListener('drop', [ '$event' ])
onDrop(event: MouseEvent): void {
const transfer = this._getTransfer(event);
if (!transfer) {
return;
}
const options = this.getOptions();
const filters = this.getFilters();
this._preventAndStop(event);
if (options) {
this.uploader?.addToQueue(transfer.files, options, filters);
}
this.fileOver.emit(false);
this.onFileDrop.emit(transfer.files);
}
@HostListener('dragover', [ '$event' ])
onDragOver(event: MouseEvent): void {
const transfer = this._getTransfer(event);
if (!this._haveFiles(transfer.types)) {
return;
}
transfer.dropEffect = 'copy';
this._preventAndStop(event);
this.fileOver.emit(true);
}
@HostListener('dragleave', [ '$event' ])
onDragLeave(event: MouseEvent): void {
if ((this as any).element) {
if (event.currentTarget === (this as any).element[ 0 ]) {
return;
}
}
this._preventAndStop(event);
this.fileOver.emit(false);
}
protected _getTransfer(event: any): any {
return event.dataTransfer ? event.dataTransfer : event.originalEvent.dataTransfer; // jQuery fix;
}
protected _preventAndStop(event: MouseEvent): void {
event.preventDefault();
event.stopPropagation();
}
protected _haveFiles(types: any): boolean {
if (!types) {
return false;
}
if (types.indexOf) {
return types.indexOf('Files') !== -1;
} else if (types.contains) {
return types.contains('Files');
} else {
return false;
}
}
}

View File

@@ -1,154 +0,0 @@
import { FileLikeObject } from './file-like-object.class';
import { FileUploader, ParsedResponseHeaders, FileUploaderOptions } from './file-uploader.class';
export class FileItem {
file: FileLikeObject;
_file: File;
alias?: string;
url = '/';
method?: string;
headers: any = [];
withCredentials = true;
formData: any = [];
isReady = false;
isUploading = false;
isUploaded = false;
isSuccess = false;
isCancel = false;
isError = false;
progress = 0;
index?: number;
_xhr?: XMLHttpRequest;
_form: any;
protected uploader: FileUploader;
protected some: File;
protected options: FileUploaderOptions;
constructor(uploader: FileUploader, some: File, options: FileUploaderOptions) {
this.uploader = uploader;
this.some = some;
this.options = options;
this.file = new FileLikeObject(some);
this._file = some;
if (uploader.options) {
this.method = uploader.options.method || 'POST';
this.alias = uploader.options.itemAlias || 'file';
}
this.url = uploader.options.url;
}
upload(): void {
try {
this.uploader.uploadItem(this);
} catch (e) {
this.uploader._onCompleteItem(this, '', 0, {});
this.uploader._onErrorItem(this, '', 0, {});
}
}
cancel(): void {
this.uploader.cancelItem(this);
}
remove(): void {
this.uploader.removeFromQueue(this);
}
onBeforeUpload(): void {
return void 0;
}
onBuildForm(form: any): any {
return { form };
}
onProgress(progress: number): any {
return { progress };
}
onSuccess(response: string, status: number, headers: ParsedResponseHeaders): any {
return { response, status, headers };
}
onError(response: string, status: number, headers: ParsedResponseHeaders): any {
return { response, status, headers };
}
onCancel(response: string, status: number, headers: ParsedResponseHeaders): any {
return { response, status, headers };
}
onComplete(response: string, status: number, headers: ParsedResponseHeaders): any {
return { response, status, headers };
}
_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();
}
_onBuildForm(form: any): void {
this.onBuildForm(form);
}
_onProgress(progress: number): void {
this.progress = progress;
this.onProgress(progress);
}
_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 = undefined;
this.onSuccess(response, status, headers);
}
_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 = undefined;
this.onError(response, status, headers);
}
_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 = undefined;
this.onCancel(response, status, headers);
}
_onComplete(response: string, status: number, headers: ParsedResponseHeaders): void {
this.onComplete(response, status, headers);
if (this.uploader.options.removeAfterUpload) {
this.remove();
}
}
_prepareToUploading(): void {
this.index = this.index || ++this.uploader._nextIndex;
this.isReady = true;
}
}

View File

@@ -1,28 +0,0 @@
export class FileLikeObject {
lastModifiedDate: any;
size: any;
type?: string;
name?: string;
rawFile: HTMLInputElement | File;
constructor(fileOrInput: HTMLInputElement | File) {
this.rawFile = fileOrInput;
const fakePathOrObject = fileOrInput instanceof HTMLInputElement ? fileOrInput.value : fileOrInput;
const postfix = typeof fakePathOrObject === 'string' ? 'FakePath' : 'Object';
const method = `_createFrom${postfix}`;
(this as any)[ method ](fakePathOrObject);
}
_createFromFakePath(path: string): void {
this.lastModifiedDate = void 0;
this.size = void 0;
this.type = `like/${path.slice(path.lastIndexOf('.') + 1).toLowerCase()}`;
this.name = path.slice(path.lastIndexOf('/') + path.lastIndexOf('\\') + 2);
}
_createFromObject(object: { size: number, type: string, name: string }): void {
this.size = object.size;
this.type = object.type;
this.name = object.name;
}
}

View File

@@ -1,41 +0,0 @@
import { Directive, EventEmitter, ElementRef, Input, HostListener, Output } from '@angular/core';
import { FileUploader, FileUploaderOptions } from './file-uploader.class';
@Directive({ selector: '[ng2FileSelect]' })
export class FileSelectDirective {
@Input() uploader?: FileUploader;
// eslint-disable-next-line @angular-eslint/no-output-on-prefix
@Output() onFileSelected: EventEmitter<File[]> = new EventEmitter<File[]>();
protected element: ElementRef;
constructor(element: ElementRef) {
this.element = element;
}
getOptions(): FileUploaderOptions | undefined {
return this.uploader?.options;
}
getFilters(): string {
return '';
}
isEmptyAfterSelection(): boolean {
return !!this.element.nativeElement.attributes.multiple;
}
@HostListener('change')
onChange(): void {
const files = this.element.nativeElement.files;
const options = this.getOptions();
const filters = this.getFilters();
this.uploader?.addToQueue(files, options, filters);
this.onFileSelected.emit(files);
if (this.isEmptyAfterSelection()) {
this.element.nativeElement.value = '';
}
}
}

View File

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

View File

@@ -1,513 +0,0 @@
import { EventEmitter } from '@angular/core';
import { FileLikeObject } from './file-like-object.class';
import { FileItem } from './file-item.class';
import { FileType } from './file-type.class';
function isFile(value: any): boolean {
return (File && value instanceof File);
}
export interface Headers {
name: string;
value: string;
}
export interface ParsedResponseHeaders { [ headerFieldName: string ]: string }
export interface FilterFunction {
name: string;
fn(item: FileLikeObject, options?: FileUploaderOptions): boolean;
}
export interface FileUploaderOptions {
allowedMimeType?: string[];
allowedFileType?: string[];
autoUpload?: boolean;
isHTML5?: boolean;
filters?: FilterFunction[];
headers?: Headers[];
method?: string;
authToken?: string;
maxFileSize?: number;
queueLimit?: number;
removeAfterUpload?: boolean;
url: string;
disableMultipart?: boolean;
itemAlias?: string;
authTokenHeader?: string;
additionalParameter?: { [ key: string ]: any };
parametersBeforeFiles?: boolean;
// eslint-disable-next-line @typescript-eslint/ban-types
formatDataFunction?: Function;
formatDataFunctionIsAsync?: boolean;
}
export class FileUploader {
authToken?: string;
isUploading = false;
queue: FileItem[] = [];
progress = 0;
_nextIndex = 0;
autoUpload: any;
authTokenHeader?: string;
response: EventEmitter<any>;
options: FileUploaderOptions = {
autoUpload: false,
isHTML5: true,
filters: [],
removeAfterUpload: false,
disableMultipart: false,
formatDataFunction: (item: FileItem) => item._file,
formatDataFunctionIsAsync: false,
url: ''
};
protected _failFilterIndex?: number;
constructor(options: FileUploaderOptions) {
this.setOptions(options);
this.response = new EventEmitter<string>();
}
setOptions(options: FileUploaderOptions): void {
this.options = Object.assign(this.options, options);
this.authToken = this.options.authToken;
this.authTokenHeader = this.options.authTokenHeader || 'Authorization';
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.allowedFileType) {
this.options.filters?.unshift({ name: 'fileType', fn: this._fileTypeFilter });
}
if (this.options.allowedMimeType) {
this.options.filters?.unshift({ name: 'mimeType', fn: this._mimeTypeFilter });
}
for (let i = 0; i < this.queue.length; i++) {
this.queue[ i ].url = this.options.url;
}
}
addToQueue(files: File[], _options?: FileUploaderOptions, filters?: [] | string): void {
let options = _options;
const list: File[] = [];
for (const file of files) {
list.push(file);
}
const arrayOfFilters = this._getFilters(filters);
const count = this.queue.length;
const addedFileItems: FileItem[] = [];
list.map((some: File) => {
if (!options) {
options = this.options;
}
const temp = new FileLikeObject(some);
if (this._isValidFile(temp, arrayOfFilters, options)) {
const fileItem = new FileItem(this, some, options);
addedFileItems.push(fileItem);
this.queue.push(fileItem);
this._onAfterAddingFile(fileItem);
} else {
if (this._failFilterIndex) {
const filter = arrayOfFilters[ this._failFilterIndex ];
this._onWhenAddingFileFailed(temp, filter, options);
}
}
});
if (this.queue.length !== count) {
this._onAfterAddingAll(addedFileItems);
this.progress = this._getTotalProgress();
}
this._render();
if (this.options.autoUpload) {
this.uploadAll();
}
}
removeFromQueue(value: FileItem): void {
const index = this.getIndexOfItem(value);
const item = this.queue[ index ];
if (item.isUploading) {
item.cancel();
}
this.queue.splice(index, 1);
this.progress = this._getTotalProgress();
}
clearQueue(): void {
while (this.queue.length) {
this.queue[ 0 ].remove();
}
this.progress = 0;
}
uploadItem(value: FileItem): void {
const index = this.getIndexOfItem(value);
const item = this.queue[ index ];
const transport = this.options.isHTML5 ? '_xhrTransport' : '_iframeTransport';
item._prepareToUploading();
if (this.isUploading) {
return;
}
this.isUploading = true;
(this as any)[ transport ](item);
}
cancelItem(value: FileItem): void {
const index = this.getIndexOfItem(value);
const item = this.queue[ index ];
const prop = this.options.isHTML5 ? item._xhr : item._form;
if (item && item.isUploading) {
prop.abort();
}
}
uploadAll(): void {
const items = this.getNotUploadedItems().filter((item: FileItem) => !item.isUploading);
if (!items.length) {
return;
}
items.map((item: FileItem) => item._prepareToUploading());
items[ 0 ].upload();
}
cancelAll(): void {
const items = this.getNotUploadedItems();
items.map((item: FileItem) => item.cancel());
}
isFile(value: any): boolean {
return isFile(value);
}
isFileLikeObject(value: any): boolean {
return value instanceof FileLikeObject;
}
getIndexOfItem(value: any): number {
return typeof value === 'number' ? value : this.queue.indexOf(value);
}
getNotUploadedItems(): any[] {
return this.queue.filter((item: FileItem) => !item.isUploaded);
}
getReadyItems(): any[] {
return this.queue
.filter((item: FileItem) => (item.isReady && !item.isUploading))
.sort((item1: any, item2: any) => item1.index - item2.index);
}
onAfterAddingAll(fileItems: any): any {
return { fileItems };
}
onBuildItemForm(fileItem: FileItem, form: any): any {
return { fileItem, form };
}
onAfterAddingFile(fileItem: FileItem): any {
return { fileItem };
}
onWhenAddingFileFailed(item: FileLikeObject, filter: any, options: any): any {
return { item, filter, options };
}
onBeforeUploadItem(fileItem: FileItem): any {
return { fileItem };
}
onProgressItem(fileItem: FileItem, progress: any): any {
return { fileItem, progress };
}
onProgressAll(progress: any): any {
return { progress };
}
onSuccessItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
return { item, response, status, headers };
}
onErrorItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
return { item, response, status, headers };
}
onCancelItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
return { item, response, status, headers };
}
onCompleteItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
return { item, response, status, headers };
}
onCompleteAll(): any {
return void 0;
}
_mimeTypeFilter(item: FileLikeObject): boolean {
return !(item?.type && this.options.allowedMimeType && this.options.allowedMimeType?.indexOf(item.type) === -1);
}
_fileSizeFilter(item: FileLikeObject): boolean {
return !(this.options.maxFileSize && item.size > this.options.maxFileSize);
}
_fileTypeFilter(item: FileLikeObject): boolean {
return !(this.options.allowedFileType &&
this.options.allowedFileType.indexOf(FileType.getMimeClass(item)) === -1);
}
_onErrorItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): void {
item._onError(response, status, headers);
this.onErrorItem(item, response, status, headers);
}
_onCompleteItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): void {
item._onComplete(response, status, headers);
this.onCompleteItem(item, response, status, headers);
const nextItem = this.getReadyItems()[ 0 ];
this.isUploading = false;
if (nextItem) {
nextItem.upload();
return;
}
this.onCompleteAll();
this.progress = this._getTotalProgress();
this._render();
}
protected _headersGetter(parsedHeaders: ParsedResponseHeaders): any {
return (name: any): any => {
if (name) {
return parsedHeaders[ name.toLowerCase() ] || undefined;
}
return parsedHeaders;
};
}
protected _xhrTransport(item: FileItem): any {
// tslint:disable-next-line:no-this-assignment
// eslint-disable-next-line @typescript-eslint/no-this-alias
const that = this;
const xhr = item._xhr = new XMLHttpRequest();
let sendable: any;
this._onBeforeUploadItem(item);
if (typeof item._file.size !== 'number') {
throw new TypeError('The file specified is no longer valid');
}
if (!this.options.disableMultipart) {
sendable = new FormData();
this._onBuildItemForm(item, sendable);
const appendFile = () => sendable.append(item.alias, item._file, item.file.name);
if (!this.options.parametersBeforeFiles) {
appendFile();
}
// For AWS, Additional Parameters must come BEFORE Files
if (this.options.additionalParameter !== undefined) {
Object.keys(this.options.additionalParameter).forEach((key: string) => {
let paramVal = this.options.additionalParameter?.[ key ];
// Allow an additional parameter to include the filename
if (typeof paramVal === 'string' && paramVal.indexOf('{{file_name}}') >= 0 && item.file?.name) {
paramVal = paramVal.replace('{{file_name}}', item.file.name);
}
sendable.append(key, paramVal);
});
}
if (appendFile && this.options.parametersBeforeFiles) {
appendFile();
}
} else {
if (this.options.formatDataFunction) {
sendable = this.options.formatDataFunction(item);
}
}
xhr.upload.onprogress = (event: any) => {
const progress = Math.round(event.lengthComputable ? event.loaded * 100 / event.total : 0);
this._onProgressItem(item, progress);
};
xhr.onload = () => {
const headers = this._parseHeaders(xhr.getAllResponseHeaders());
const response = this._transformResponse(xhr.response, headers);
const gist = this._isSuccessCode(xhr.status) ? 'Success' : 'Error';
const method = `_on${gist}Item`;
(this as any)[ method ](item, response, xhr.status, headers);
this._onCompleteItem(item, response, xhr.status, headers);
};
xhr.onerror = () => {
const headers = this._parseHeaders(xhr.getAllResponseHeaders());
const response = this._transformResponse(xhr.response, headers);
this._onErrorItem(item, response, xhr.status, headers);
this._onCompleteItem(item, response, xhr.status, headers);
};
xhr.onabort = () => {
const headers = this._parseHeaders(xhr.getAllResponseHeaders());
const response = this._transformResponse(xhr.response, headers);
this._onCancelItem(item, response, xhr.status, headers);
this._onCompleteItem(item, response, xhr.status, headers);
};
if (item.method && item.url) {
xhr.open(item.method, item.url, true);
}
xhr.withCredentials = item.withCredentials;
if (this.options.headers) {
for (const header of this.options.headers) {
xhr.setRequestHeader(header.name, header.value);
}
}
if (item.headers.length) {
for (const header of item.headers) {
xhr.setRequestHeader(header.name, header.value);
}
}
if (this.authToken && this.authTokenHeader) {
xhr.setRequestHeader(this.authTokenHeader, this.authToken);
}
xhr.onreadystatechange = function () {
if (xhr.readyState == XMLHttpRequest.DONE) {
that.response.emit(xhr.responseText);
}
};
if (this.options.formatDataFunctionIsAsync) {
sendable.then(
(result: any) => xhr.send(JSON.stringify(result))
);
} else {
xhr.send(sendable);
}
this._render();
}
protected _getTotalProgress(value = 0): number {
if (this.options.removeAfterUpload) {
return value;
}
const notUploaded = this.getNotUploadedItems().length;
const uploaded = notUploaded ? this.queue.length - notUploaded : this.queue.length;
const ratio = 100 / this.queue.length;
const current = value * ratio / 100;
return Math.round(uploaded * ratio + current);
}
protected _getFilters(filters?: FilterFunction[] | string): FilterFunction[] | [] {
if (!filters) {
return this.options?.filters || [];
}
if (Array.isArray(filters)) {
return filters;
}
if (typeof filters === 'string') {
const names = filters.match(/[^\s,]+/g);
return this.options?.filters || []
.filter((filter: any) => names?.indexOf(filter.name) !== -1);
}
return this.options?.filters || [];
}
protected _render(): any {
return void 0;
}
protected _queueLimitFilter(): boolean {
return this.options.queueLimit === undefined || this.queue.length < this.options.queueLimit;
}
protected _isValidFile(file: FileLikeObject, filters: FilterFunction[], options: FileUploaderOptions): boolean {
this._failFilterIndex = -1;
return !filters.length ? true : filters.every((filter: FilterFunction) => {
if (this._failFilterIndex) {
this._failFilterIndex++;
}
return filter.fn.call(this, file, options);
});
}
protected _isSuccessCode(status: number): boolean {
return (status >= 200 && status < 300) || status === 304;
}
protected _transformResponse(response: string, headers: ParsedResponseHeaders): string {
return response;
}
protected _parseHeaders(headers: string): ParsedResponseHeaders {
const parsed: any = {};
let key: any;
let val: any;
let i: any;
if (!headers) {
return parsed;
}
headers.split('\n').map((line: any) => {
i = line.indexOf(':');
key = line.slice(0, i).trim().toLowerCase();
val = line.slice(i + 1).trim();
if (key) {
parsed[ key ] = parsed[ key ] ? parsed[ key ] + ', ' + val : val;
}
});
return parsed;
}
protected _onWhenAddingFileFailed(item: FileLikeObject, filter: any, options: any): void {
this.onWhenAddingFileFailed(item, filter, options);
}
protected _onAfterAddingFile(item: FileItem): void {
this.onAfterAddingFile(item);
}
protected _onAfterAddingAll(items: any): void {
this.onAfterAddingAll(items);
}
protected _onBeforeUploadItem(item: FileItem): void {
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 {
const 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

@@ -1,26 +0,0 @@
module.exports = {
displayName: 'ng2-file-upload',
preset: '../../jest.preset.js',
setupFilesAfterEnv: ['<rootDir>/testing/test-setup.ts'],
globals: {
'ts-jest': {
tsconfig: '<rootDir>/tsconfig.spec.json',
astTransformers: {
before: [
'jest-preset-angular/build/InlineFilesTransformer',
'jest-preset-angular/build/StripStylesTransformer',
]
}
}
},
transform: {
'^.+\\.[tj]sx?$': 'ts-jest'
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
coverageDirectory: '../../coverage/libs/ng2-file-upload',
snapshotSerializers: [
'jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js',
'jest-preset-angular/build/AngularSnapshotSerializer.js',
'jest-preset-angular/build/HTMLCommentSerializer.js',
]
};

View File

@@ -1,7 +0,0 @@
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/libs/ng2-file-upload",
"lib": {
"entryFile": "index.ts"
}
}

View File

@@ -1 +0,0 @@
import 'jest-preset-angular';

View File

@@ -1,28 +0,0 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.lib.prod.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"compilerOptions": {
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"angularCompilerOptions": {
"strictInjectionParameters": true,
"strictTemplates": true,
"fullTemplateTypeCheck": true
}
}

View File

@@ -1,23 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"target": "es2015",
"declaration": true,
"declarationMap": true,
"inlineSources": true,
"types": [],
"lib": ["dom", "es2018"]
},
"angularCompilerOptions": {
"skipTemplateCodegen": true,
"strictMetadataEmit": true,
"enableResourceInlining": true
},
"include": [
"**/*.ts"
],
"exclude": [
"**/*.spec.ts"
]
}

View File

@@ -1,10 +0,0 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.lib.json",
"compilerOptions": {
"declarationMap": false
},
"angularCompilerOptions": {
"enableIvy": false
}
}

View File

@@ -1,12 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}

38
nx.json
View File

@@ -1,38 +0,0 @@
{
"npmScope": "ng2-file-upload-demo",
"implicitDependencies": {
"angular.json": "*",
"package.json": "*",
"tsconfig.json": "*",
"tslint.json": "*",
".eslintrc.json": "*",
"nx.json": "*"
},
"projects": {
"ng2-file-upload": {
"tags": [
"lib"
]
},
"ng2-file-upload-demo": {
"tags": [],
"implicitDependencies": [
"ng2-file-upload"
]
}
},
"tasksRunnerOptions": {
"default": {
"runner": "@nrwl/workspace/tasks-runners/default",
"options": {
"cacheableOperations": [
"build",
"lint",
"test",
"e2e"
]
}
}
}
}

36945
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,101 +1,128 @@
{
"name": "ng2-file-upload-base",
"version": "2.0.0-0",
"name": "ng2-chunk-file-upload-base",
"version": "1.3.0",
"private": true,
"description": "Angular file upload directives",
"description": "Angular file upload directives with Chunk Upload",
"scripts": {
"ng": "nx",
"start": "ng serve",
"demo.build": "ng build",
"demo.build-prod": "ng build --prod",
"build": "nx run ng2-file-upload:build",
"build-prod": "nx run ng2-file-upload:build:production",
"build.watch": "nx run ng2-file-upload:build --watch",
"test": "nx run-many --all --target=test",
"version": "nx run ng2-file-upload:version",
"lint": "nx run-many --all --target=lint",
"pretest": "run-s lint build",
"test-coverage": "nx run-many --all --target=test --codeCoverage",
"lite-server": "lite-server -c demo/bs-config.json",
"demo.serve": "run-s build link demo.build lite-server",
"demo.gh-pages": "run-s build demo.build demo.deploy",
"demo.deploy": "gh-pages -d dist/apps/ng2-file-upload",
"postinstall": "node ./decorate-angular-cli.js",
"flow.github-release": "conventional-github-releaser -p angular"
"demo.build": "ng build -prod --aot",
"demo.deploy": "gh-pages -d demo/dist",
"link": "ngm link -p src --here",
"lint": "exit 0",
"disable-lint": "tslint \"**/*.ts\" -c tslint.json --fix --type-check -t prose -e \"node_modules/**\" -e \"dist/**\" -e \"temp/**\" -e \"scripts/docs/**\"",
"flow.changelog": "conventional-changelog -i CHANGELOG.md -s -p angular",
"flow.github-release": "conventional-github-releaser -p angular",
"build": "ngm build -p src --clean",
"build.watch": "ngm build -p src --watch --skip-bundles",
"start": "ng serve --aot",
"pretest": "run-s lint build link",
"test": "ng test -sr",
"test-coverage": "ng test -sr -cc",
"version": "npm run flow.changelog && git add -A"
},
"main": "bundles/ng2-chunk-file-upload.umd.js",
"module": "index.js",
"typings": "index.d.ts",
"keywords": [
"angular",
"angular2",
"bootstrap",
"angularjs",
"twitter-bootstrap",
"file-upload",
"angular-file-upload"
"angular-file-upload",
"chunk-file-upload",
"azure-blob-storage"
],
"author": "Dmitriy Shekhovtsov <valorkin@gmail.com>",
"author": "Paulo Peres Jr <paulo@myog.io>",
"license": "MIT",
"repository": {
"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": {
"url": "https://github.com/valor-software/ng2-file-upload/issues"
"url": "https://github.com/PauloPeres/ng2-chunk-file-upload/issues"
},
"homepage": "https://github.com/PauloPeres/ng2-chunk-file-upload#readme",
"dependencies": {},
"peerDependencies": {
"@angular/common": "^4.3.0 || >=4.3.0",
"@angular/core": "^4.3.0 || >=4.3.0",
"@angular/http": "^4.3.0 || >=4.3.0"
},
"homepage": "https://github.com/valor-software/ng2-file-upload#readme",
"peerDependencies": {},
"devDependencies": {
"@angular-devkit/build-angular": "~0.1102.13",
"@angular-devkit/build-ng-packagr": "^0.1002.0",
"@angular/animations": "~11.2.14",
"@angular/cli": "~11.2.14",
"@angular/common": "~11.2.14",
"@angular/compiler": "~11.2.14",
"@angular/compiler-cli": "~11.2.14",
"@angular/core": "~11.2.14",
"@angular/forms": "~11.2.14",
"@angular/platform-browser": "~11.2.14",
"@angular/platform-browser-dynamic": "~11.2.14",
"@angular-eslint/eslint-plugin": "4.3.0",
"@angular-eslint/eslint-plugin-template": "4.3.0",
"@angular-eslint/template-parser": "4.3.0",
"@nrwl/angular": "11.2.12",
"@nrwl/cli": "11.2.12",
"@nrwl/node": "11.2.12",
"@nrwl/eslint-plugin-nx": "11.2.12",
"@nrwl/jest": "11.2.12",
"@nrwl/linter": "11.2.12",
"@types/fs-extra": "9.0.7",
"@types/jest": "26.0.20",
"@types/node": "^12.11.1",
"@types/webpack": "^5.0.0",
"@typescript-eslint/eslint-plugin": "~4.28.3",
"@typescript-eslint/parser": "~4.28.3",
"bootstrap": "3.3.7",
"@angular-devkit/build-angular": "~0.6.3",
"@angular/cdk": "^6.1.0",
"@angular/cli": "^6.0.3",
"@angular/common": "^6.0.1",
"@angular/compiler": "^6.0.1",
"@angular/compiler-cli": "^6.0.1",
"@angular/core": "^6.0.1",
"@angular/forms": "^6.0.1",
"@angular/http": "^6.0.1",
"@angular/language-service": "^6.0.1",
"@angular/material": "^6.1.0",
"@angular/platform-browser": "^6.0.1",
"@angular/platform-browser-dynamic": "^6.0.1",
"@angular/router": "^6.0.1",
"@angular/tsc-wrapped": "4.4.6",
"@types/jasmine": "2.8.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",
"classlist-polyfill": "1.2.0",
"codecov": "3.8.2",
"codelyzer": "^6.0.0",
"conventional-changelog-cli": "2.1.1",
"conventional-github-releaser": "3.1.5",
"core-js": "^3.14.0",
"eslint": "7.22.0",
"eslint-config-prettier": "7.2.0",
"fs-extra": "9.1.0",
"gh-pages": "3.2.2",
"codecov": "3.0.2",
"codelyzer": "~4.3.0",
"conventional-changelog-cli": "1.3.22",
"conventional-github-releaser": "2.0.2",
"core-js": "^2.4.1",
"cpy": "7.0.0",
"cpy-cli": "1.0.1",
"del-cli": "1.1.0",
"gh-pages": "1.1.0",
"gitignore-to-glob": "0.3.0",
"google-code-prettify": "1.0.5",
"html-loader": "^1.3.2",
"jest": "26.6.3",
"jest-createspyobj": "2.0.0",
"jest-preset-angular": "8.3.2",
"markdown-loader": "^6.0.0",
"ng-packagr": "^11.2.4",
"ngx-bootstrap": "6.2.0",
"npm-run-all": "^4.1.5",
"protractor": "~7.0.0",
"raw-loader": "^4.0.2",
"rxjs": "^6.6.0",
"ts-helpers": "^1.1.2",
"ts-jest": "26.5.1",
"ts-node": "8.3.0",
"tslint": "^6.1.0",
"tslint-config-valorsoft": "^2.2.1",
"typescript": "4.1.5",
"zone.js": "~0.11.3"
"html-loader": "0.5.5",
"jasmine": "3.1.0",
"jasmine-core": "3.1.0",
"jasmine-data-provider": "2.2.0",
"jasmine-spec-reporter": "4.2.1",
"jquery": "^1.9.1",
"karma": "2.0.2",
"karma-chrome-launcher": "^2.0.0",
"karma-cli": "^1.0.1",
"karma-coverage-istanbul-reporter": "^2.0.1",
"karma-jasmine": "^1.0.2",
"karma-remap-istanbul": "0.6.0",
"karma-sauce-launcher": "1.2.0",
"lite-server": "2.3.0",
"lodash": "4.17.10",
"markdown-loader": "^2.0.2",
"marked": "0.4.0",
"ngm-cli": "1.0.4",
"ngx-bootstrap": "3.0.0",
"npm-run-all": "^4.0.1",
"popper.js": "^1.14.3",
"pre-commit": "1.2.2",
"protractor": "5.3.2",
"reflect-metadata": "0.1.12",
"require-dir": "1.0.0",
"rxjs": "^6.2.0",
"rxjs-compat": "^6.1.0",
"rxjs-tslint": "^0.1.4",
"systemjs-builder": "0.16.13",
"ts-helpers": "^1.1.1",
"ts-node": "6.0.3",
"tslint": "5.10.0",
"typedoc": "0.11.1",
"typescript": "^2.7.2",
"wallaby-webpack": "3.9.8",
"webdriver-manager": "12.0.6",
"zone.js": "0.8.26"
},
"contributors": [
{
@@ -117,10 +144,11 @@
"name": "Oleksandr Telnov",
"email": "otelnov@gmail.com",
"url": "https://github.com/otelnov"
},
{
"name": "Paulo Peres Jr",
"email": "paulo@myog.io",
"url": "https://github.com/PauloPeres/"
}
],
"dependencies": {
"@nrwl/workspace": "^12.8.0",
"tslib": "^2.0.0"
}
]
}

1
scripts/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
!**/*.js

21
scripts/matchers.ts Normal file
View File

@@ -0,0 +1,21 @@
// tslint:disable
/**
* @copyright Angular ng-bootstrap team
*/
beforeEach(() => {
jasmine.addMatchers({
toHaveCssClass(/*util, customEqualityTests*/) {
return {compare: buildError(false), negativeCompare: buildError(true)};
function buildError(isNot) {
return function (actual, className) {
const orNot = isNot ? 'not ' : '';
return {
pass: actual.classList.contains(className) === !isNot,
message: `Expected ${actual.outerHTML} ${orNot} to contain the CSS class "${className}"`
};
};
}
}
});
});

View File

@@ -1,5 +0,0 @@
// This file includes polyfills needed by Angular 2 and is loaded before
// the app. You can add your own extra polyfills to this file.
import 'ts-helpers';
import 'zone.js/dist/zone';
import 'classlist-polyfill';

18
scripts/sauce-browsers.js Normal file
View File

@@ -0,0 +1,18 @@
module.exports.customLaunchers = function customLaunchers() {
return {
sl_chrome: {base: 'SauceLabs', browserName: 'chrome'},
sl_chrome_1: {base: 'SauceLabs', browserName: 'chrome', version: 'latest-1'},
sl_firefox: {base: 'SauceLabs', browserName: 'firefox'},
sl_firefox_1: {base: 'SauceLabs', browserName: 'firefox', version: 'latest-1'},
sl_ie9: {base: 'SauceLabs', browserName: 'internet explorer', platform: 'Windows 2008', version: '9'},
'SL_IE10': {base: 'SauceLabs', browserName: 'internet explorer', platform: 'Windows 2012', version: '10'},
'SL_IE11': {base: 'SauceLabs', browserName: 'internet explorer', platform: 'Windows 8.1', version: '11'},
'SL_EDGE': {base: 'SauceLabs', browserName: 'MicrosoftEdge', platform: 'Windows 10', version: '13.10586'},
'SL_IOS9': {base: 'SauceLabs', browserName: 'iphone', platform: 'OS X 10.10', version: '9.3'},
'SL_IOS10': {base: 'SauceLabs', browserName: 'iphone', platform: 'OS X 10.10', version: '10.0'},
'SL_ANDROID4.4': {base: 'SauceLabs', browserName: 'android', platform: 'Linux', version: '4.4'},
'SL_ANDROID5': {base: 'SauceLabs', browserName: 'android', platform: 'Linux', version: '5.1'},
'SL_SAFARI9': {base: 'SauceLabs', browserName: 'safari', platform: 'OS X 10.11', version: '9.0'}
};
};

View File

@@ -1,13 +0,0 @@
import { readJson, writeJson } from 'fs-extra';
const libPackage = './libs/ng2-file-upload/package.json';
const mainPackage = './package.json';
(async () => {
const version = await readJson(mainPackage).then(json => json.version);
const packageJson = await readJson(libPackage);
if (packageJson.version) {
packageJson.version = version;
}
await writeJson(libPackage, packageJson, { spaces: 2 });
})();

37
scripts/test.ts Normal file
View File

@@ -0,0 +1,37 @@
import '../demo/src/polyfills.ts';
import 'zone.js/dist/long-stack-trace-zone';
import 'zone.js/dist/proxy.js';
import 'zone.js/dist/sync-test';
import 'zone.js/dist/jasmine-patch';
import 'zone.js/dist/async-test';
import 'zone.js/dist/fake-async-test';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
import './matchers';
// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any.
declare var __karma__: any;
declare var require: any;
// Prevent Karma from running prematurely.
__karma__.loaded = Function.prototype;
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
let context = require.context('../demo/src', true, /\.spec\.ts/);
// And load the modules.
context.keys().map(context);
let context2 = require.context('../src/spec', true, /\.spec\.ts/);
context2.keys().map(context2);
// Finally, start Karma to run the tests.
__karma__.start();

View File

@@ -9,9 +9,9 @@ declare const ENV:string;
declare const PR:any;
// declare const global:any;
// eslint-disable-next-line @typescript-eslint/prefer-namespace-keyword
declare module jasmine {
interface Matchers<T> {
interface Matchers {
toHaveCssClass(expected: any): boolean;
}
}

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

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

View File

@@ -0,0 +1,210 @@
import { HttpHeaders } from '@angular/common/http';
import { FileLikeObject } from './file-like-object.class';
import { FileUploader, FileUploaderOptions } from './file-uploader.class';
import { FileChunk } from './file-chunk.class'
export class FileItem {
public file: FileLikeObject;
public _file: File;
public id: any;
public alias: string;
public url: string = '/';
public method: string;
public headers: any = [];
public withCredentials: boolean = true;
public formData: any = [];
public isReady: boolean = false;
public isUploading: boolean = false;
public isUploaded: boolean = false;
public isSuccess: boolean = false;
public isCancel: boolean = false;
public isError: boolean = false;
public isRemoving: boolean = false;
public progress: number = 0;
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;
public constructor(uploader: FileUploader, some: File, options: FileUploaderOptions) {
this.uploader = uploader;
this.some = some;
this.options = options;
this.file = new FileLikeObject(some);
this._file = some;
if (uploader.options) {
this.method = uploader.options.method || 'POST';
this.alias = uploader.options.itemAlias || 'file';
}
this.url = uploader.options.url;
}
public upload(): void {
try {
this.uploader.uploadItem(this);
} catch (e) {
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);
if (this.uploader.options.removeAfterUpload) {
this.remove();
}
}
public _onCompleteChunk(response: string, status: number, headers: HttpHeaders): void {
this.chunkRetries = 0;
this._onCompleteChunkCallNext();
this.onCompleteChunk(response, status, headers);
}
public _onCompleteChunkCallNext(): void {
this.uploader.uploaderService.uploadFile(this,this.uploader.options);
this.prepareNextChunk()
}
public _onErrorChunk(response: string, status: number, headers: HttpHeaders): void {
if (this.chunkRetries > this.chunkTotalRetries) {
this.uploader.onErrorItem(this, response, status, headers);
this.uploader.onCompleteItem(this, response, status, headers);
} else {
this.chunkRetries++;
this.fileChunks.retrocedeChunk();
this._onCompleteChunkCallNext();
}
}
public _prepareToUploading(): void {
this.index = this.index || ++this.uploader._nextIndex;
this.isReady = true;
}
}

View File

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

View File

@@ -0,0 +1,41 @@
import { Directive, EventEmitter, ElementRef, Input, HostListener, Output } from '@angular/core';
import { FileUploader } from './file-uploader.class';
@Directive({ selector: '[ng2FileSelect]' })
export class FileSelectDirective {
@Input() public uploader: FileUploader;
@Output() public onFileSelected: EventEmitter<File[]> = new EventEmitter<File[]>();
protected element: ElementRef;
public constructor(element: ElementRef) {
this.element = element;
}
public getOptions(): any {
return this.uploader.options;
}
public getFilters(): any {
return {};
}
public isEmptyAfterSelection(): boolean {
return !!this.element.nativeElement.attributes.multiple;
}
@HostListener('change')
public onChange(): any {
let files = this.element.nativeElement.files;
let options = this.getOptions();
let filters = this.getFilters();
this.uploader.addToQueue(files, options, filters);
this.onFileSelected.emit(files);
if (this.isEmptyAfterSelection()) {
this.element.nativeElement.value = '';
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,484 @@
import { Headers } from './file-uploader.class';
import { EventEmitter } from '@angular/core';
import { FileLikeObject } from './file-like-object.class';
import { FileItem } from './file-item.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 {
return (File && value instanceof File);
}
export interface Headers {
name: string;
value: string;
}
export type FilterFunction = {
name: string,
fn: (item?: FileLikeObject, options?: FileUploaderOptions) => boolean
};
export interface FileUploaderOptions {
uploaderService: any;
allowedMimeType?: string[];
allowedFileType?: string[];
autoUpload?: boolean;
isHTML5?: boolean;
filters?: FilterFunction[];
headers?: Headers[];
method?: string;
authToken?: string;
maxFileSize?: number;
queueLimit?: number;
removeAfterUpload?: boolean;
url?: string;
disableMultipart?: boolean;
itemAlias?: string;
authTokenHeader?: string;
additionalParameter?: { [key: string]: any };
parametersBeforeFiles?: boolean;
formatDataFunction?: Function;
formatDataFunctionIsAsync?: boolean;
}
export class FileUploader {
public uploaderService: any;
public authToken: string;
public isUploading: boolean = false;
public queue: FileItem[] = [];
public progress: number = 0;
public _nextIndex: number = 0;
public autoUpload: any;
public authTokenHeader: string;
public response: EventEmitter<any>;
public chunkSize: number = null;
public options: FileUploaderOptions = {
uploaderService: null,
autoUpload: false,
isHTML5: true,
filters: [],
removeAfterUpload: false,
disableMultipart: false,
formatDataFunction: (item: FileItem) => item._file,
formatDataFunctionIsAsync: false
};
protected _failFilterIndex: number;
public constructor(options: FileUploaderOptions) {
this.setOptions(options);
this.response = new EventEmitter<any>();
}
public setOptions(options: FileUploaderOptions): void {
this.options = Object.assign(this.options, options);
this.uploaderService = this.options.uploaderService;
this.uploaderService.uploader = this;
this.authToken = this.options.authToken;
this.authTokenHeader = this.options.authTokenHeader || 'Authorization';
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.allowedFileType) {
this.options.filters.unshift({ name: 'fileType', fn: this._fileTypeFilter });
}
if (this.options.allowedMimeType) {
this.options.filters.unshift({ name: 'mimeType', fn: this._mimeTypeFilter });
}
for (let i = 0; i < this.queue.length; i++) {
this.queue[i].url = this.options.url;
}
}
public addToQueue(files: File[], options?: FileUploaderOptions, filters?: FilterFunction[] | string): void {
let list: File[] = [];
for (let file of files) {
list.push(file);
}
let arrayOfFilters = this._getFilters(filters);
let count = this.queue.length;
let addedFileItems: FileItem[] = [];
list.map((some: File) => {
if (!options) {
options = this.options;
}
let temp = new FileLikeObject(some);
if (this._isValidFile(temp, arrayOfFilters, options)) {
let fileItem = new FileItem(this, some, options);
addedFileItems.push(fileItem);
this.queue.push(fileItem);
this._onAfterAddingFile(fileItem);
} else {
let filter = arrayOfFilters[this._failFilterIndex];
this._onWhenAddingFileFailed(temp, filter, options);
}
});
if (this.queue.length !== count) {
this._onAfterAddingAll(addedFileItems);
this.progress = this._getTotalProgress();
}
this._render();
if (this.options.autoUpload) {
this.uploadAll();
}
}
public removeFromQueue(value: FileItem): void {
let index = this.getIndexOfItem(value);
let item = this.queue[index];
if (item.isUploading) {
item.cancel();
}
this.queue.splice(index, 1);
this.progress = this._getTotalProgress();
this.onRemoveItem(item);
}
public clearQueue(): void {
while (this.queue.length) {
this.queue[0].remove();
}
this.progress = 0;
}
public uploadItem(value: FileItem): void {
let index = this.getIndexOfItem(value);
let item = this.queue[index];
item._prepareToUploading();
if (this.isUploading) {
return;
}
this.isUploading = true;
this._uploadFile(item);
}
public cancelItem(value: FileItem): void {
const index = this.getIndexOfItem(value);
const item = this.queue[index];
if (item && item.isUploading) {
this.uploaderService.stopUpload()
}
}
public uploadAll(): void {
const items = this.getNotUploadedItems().filter((item: FileItem) => !item.isUploading);
if (!items.length) {
return;
}
items.map((item: FileItem) => item._prepareToUploading());
items[0].upload();
}
public cancelAll(): void {
const items = this.getNotUploadedItems();
items.map((item: FileItem) => item.cancel());
}
public isFile(value: any): boolean {
return isFile(value);
}
public isFileLikeObject(value: any): boolean {
return value instanceof FileLikeObject;
}
public getIndexOfItem(value: any): number {
return typeof value === 'number' ? value : this.queue.indexOf(value);
}
public getIsErrorItems(): any[] {
return this.queue.filter((item: FileItem) => item.isError);
}
public getIsCancelItems(): any[] {
return this.queue.filter((item: FileItem) => item.isCancel);
}
public getIsSuccessItems(): any[] {
return this.queue.filter((item: FileItem) => item.isSuccess);
}
public getAllItems(): any[] {
return this.queue;
}
public getNotUploadedItems(): any[] {
return this.queue.filter((item: FileItem) => !item.isUploaded);
}
public getReadyItems(): any[] {
return this.queue
.filter((item: FileItem) => (item.isReady && !item.isUploading))
.sort((item1: any, item2: any) => item1.index - item2.index);
}
public destroy(): void {
return void 0;
}
public onAfterAddingAll(fileItems: any): any {
return { fileItems };
}
public onBuildItemForm(fileItem: FileItem, form: any): any {
return { fileItem, form };
}
public onAfterAddingFile(fileItem: FileItem): any {
return { fileItem };
}
public onWhenAddingFileFailed(item: FileLikeObject, filter: any, options: any): any {
return { item, filter, options };
}
public onBeforeUploadItem(fileItem: FileItem): any {
return { fileItem };
}
public onProgressItem(fileItem: FileItem, progress: any): any {
return { fileItem, progress };
}
public onProgressAll(progress: any): any {
return { progress };
}
public onSuccessItem(item: FileItem, response: string, status: number, headers: HttpHeaders): any {
return { item, response, status, headers };
}
public onErrorItem(item: FileItem, response: string, status: number, headers: HttpHeaders): any {
return { item, response, status, headers };
}
public onCancelItem(item: FileItem): any {
return { item };
}
public onRemoveItem(item: FileItem): any {
return { item };
}
public onCompleteChunk(item: FileItem, response: string, status: number, headers: HttpHeaders): any {
return { item, response, status, headers };
}
public onErrorChunk(item: FileItem, response: string, status: number, headers: HttpHeaders): any {
return { item, response, status, headers };
}
public onCompleteItem(item: FileItem, response: string, status: number, headers: HttpHeaders): any {
return { item, response, status, headers };
}
public onCompleteAll(): any {
return void 0;
}
public _mimeTypeFilter(item: FileLikeObject): boolean {
return !(this.options.allowedMimeType && this.options.allowedMimeType.indexOf(item.type) === -1);
}
public _fileSizeFilter(item: FileLikeObject): boolean {
return !(this.options.maxFileSize && item.size > this.options.maxFileSize);
}
public _fileTypeFilter(item: FileLikeObject): boolean {
return !(this.options.allowedFileType &&
this.options.allowedFileType.indexOf(FileType.getMimeClass(item)) === -1);
}
public _onErrorItem(item: FileItem, response: string, status: number, headers: HttpHeaders): void {
item._onError(response, status, headers);
this.onErrorItem(item, response, status, headers);
}
public _onCompleteChunk(item: FileItem, response: string, status: number, headers: HttpHeaders): void {
this.onCompleteChunk(item, response, status, headers);
item._onCompleteChunk(response, status, headers);
this.progress = this._getTotalProgress();
this._render();
}
public _onCompleteItem(item: FileItem, response?: string, status?: number, headers?: HttpHeaders): void {
item._onComplete(response, status, headers);
this.onCompleteItem(item, response, status, headers);
let nextItem = this.getReadyItems()[0];
this.isUploading = false;
if (nextItem) {
nextItem.upload();
return;
}
this.onCompleteAll();
this.progress = this._getTotalProgress();
this._render();
}
protected _onProgress(event: HttpProgressEvent, item: FileItem) {
event = event;
let progress = (100 * event.loaded / event.total);
if (this.uploaderService.options.chunkSize > 0) {
progress = ( 100 * item.getCurrentChunk() / item.getTotalChunks() ) + (progress / item.getTotalChunks() );
}
// TODO: Check why it's not showing upload progress per item only on complete.
this._onProgressItem(item, Math.round(progress) );
}
public onProgress(event: HttpProgressEvent, item: FileItem) {
this._onProgress(event, item);
}
protected _onStart(event: HttpSentEvent, item: FileItem) {
}
public onStart(event: HttpSentEvent, item: FileItem) {
this._onStart(event, item);
}
protected _onLoad(event: HttpResponse<any>, item: FileItem) {
const headers = event.headers;
const response = this._transformResponse(event.body, headers);
const gist = this._isSuccessCode(event.status) ? 'Success' : 'Error';
const method = '_on' + gist + 'Item';
if (this.uploaderService.options.chunkSize > 0) {
if ( (item.getCurrentChunk() +1) >= item.getTotalChunks()) {
(this as any)[method](item, response, event.status, headers);
this._onCompleteItem(item, response, event.status, headers);
} else {
this._onCompleteChunk(item, response, event.status, headers);
}
} else {
(this as any)[method](item, response, event.status, headers);
this._onCompleteItem(item, response, event.status, headers);
}
}
public onLoad(event: HttpResponse<any>, item: FileItem) {
this._onLoad(event, item);
}
protected _onError(error: any, item: FileItem) {
const headers: HttpHeaders = error.Headers
const response = this._transformResponse(error.error, headers);
if (this.uploaderService.options.chunkSize > 0) {
this._onErrorChunk(item, response, error.status, headers);
} else {
this._onErrorItem(item, response, error.status, headers);
this._onCompleteItem(item, response, error.status, headers);
}
}
public onError(error: HttpErrorResponse, item: FileItem) {
this._onError(error,item);
}
protected _onAbort(error: HttpErrorResponse, item: FileItem) {
this._onCancelItem(item);
this._onCompleteItem(item);
}
public onAbort(error: HttpErrorResponse, item: FileItem) {
this._onAbort(error, item);
}
protected _uploadFile(item: FileItem): any {
this._onBeforeUploadItem(item);
if (typeof item._file.size !== 'number') {
throw new TypeError('The file specified is no longer valid');
}
this.uploaderService.uploadFile(item, this.options);
}
protected _getTotalProgress(value: number = 0): number {
if (this.options.removeAfterUpload) {
return value;
}
let notUploaded = this.getNotUploadedItems().length;
let uploaded = notUploaded ? this.queue.length - notUploaded : this.queue.length;
let ratio = 100 / this.queue.length;
let current = value * ratio / 100;
return Math.round(uploaded * ratio + current);
}
protected _getFilters(filters: FilterFunction[] | string): FilterFunction[] {
if (!filters) {
return this.options.filters;
}
if (Array.isArray(filters)) {
return filters;
}
if (typeof filters === 'string') {
let names = filters.match(/[^\s,]+/g);
return this.options.filters
.filter((filter: any) => names.indexOf(filter.name) !== -1);
}
return this.options.filters;
}
protected _render(): any {
return void 0;
}
protected _queueLimitFilter(): boolean {
return this.options.queueLimit === undefined || this.queue.length < this.options.queueLimit;
}
protected _isValidFile(file: FileLikeObject, filters: FilterFunction[], options: FileUploaderOptions): boolean {
this._failFilterIndex = -1;
return !filters.length ? true : filters.every((filter: FilterFunction) => {
this._failFilterIndex++;
return filter.fn.call(this, file, options);
});
}
protected _isSuccessCode(status: number): boolean {
return (status >= 200 && status < 300) || status === 304;
}
protected _transformResponse(response: string, headers: HttpHeaders): string {
return response;
}
protected _onWhenAddingFileFailed(item: FileLikeObject, filter: any, options: any): void {
this.onWhenAddingFileFailed(item, filter, options);
}
protected _onAfterAddingFile(item: FileItem): void {
this.onAfterAddingFile(item);
}
protected _onAfterAddingAll(items: any): void {
this.onAfterAddingAll(items);
}
protected _onBeforeUploadItem(item: FileItem): void {
item._onBeforeUpload();
this.onBeforeUploadItem(item);
}
public _onBuildItemForm(item: FileItem, form: any): void {
item._onBuildForm(form);
this.onBuildItemForm(item, form);
}
protected _onProgressItem(item: FileItem, progress: any): void {
const total = this._getTotalProgress(progress);
this.progress = total;
item._onProgress(progress);
this.onProgressItem(item, progress);
this.onProgressAll(total);
this._render();
}
protected _onErrorChunk(item: FileItem, response: string, status: number, headers: HttpHeaders): void {
item._onErrorChunk(response, status, headers);
this.onErrorChunk(item, response, status, headers)
}
protected _onSuccessItem(item: FileItem, response: string, status: number, headers: HttpHeaders): void {
item._onSuccess(response, status, headers);
this.onSuccessItem(item, response, status, headers);
}
protected _onCancelItem(item: FileItem): void {
item._onCancel();
this.onCancelItem(item);
}
}

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

@@ -1,9 +1,8 @@
export * from './file-upload/file-select.directive';
export * from './file-upload/file-drop.directive';
export * from './file-upload/file-uploader.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 { FileSelectDirective } from './file-upload/file-select.directive';

View File

@@ -0,0 +1 @@
export * from './index';

View File

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

View File

@@ -2,9 +2,9 @@ import { Component, DebugElement } from '@angular/core';
import { By } from '@angular/platform-browser';
import { inject, ComponentFixture, TestBed } from '@angular/core/testing';
import { FileUploader } from '../../file-upload/file-uploader.class';
import { FileUploadModule } from '../../file-upload/file-upload.module';
import { FileDropDirective } from '../../file-upload/file-drop.directive';
import { FileUploader } from '../file-upload/file-uploader.class';
import { FileUploadModule } from '../file-upload/file-upload.module';
import { FileDropDirective } from '../file-upload/file-drop.directive';
@Component({
selector: 'container',
@@ -57,15 +57,13 @@ describe('Directive: FileDropDirective', () => {
const options = fileDropDirective.getOptions();
// Check url set through binding
expect(options.url).toBe(hostComponent.url);
// Check default options
expect(options).toBeTruthy();
if (options) {
expect(options.url).toBe(hostComponent.url);
expect(options.autoUpload).toBeFalsy();
expect(options.isHTML5).toBeTruthy();
expect(options.removeAfterUpload).toBeFalsy();
expect(options.disableMultipart).toBeFalsy();
}
expect(options.autoUpload).toBeFalsy();
expect(options.isHTML5).toBeTruthy();
expect(options.removeAfterUpload).toBeFalsy();
expect(options.disableMultipart).toBeFalsy();
});
it('can get filters', () => {
@@ -95,8 +93,9 @@ describe('Directive: FileDropDirective', () => {
fileDropDirective.onDrop(getFakeEventData());
const uploadedFiles = getFakeEventData().dataTransfer.files;
const expectedArguments = [ uploadedFiles, fileDropDirective.getOptions(), fileDropDirective.getFilters() ];
expect(fileDropDirective.uploader.addToQueue).toHaveBeenCalledWith(uploadedFiles, fileDropDirective.getOptions(), fileDropDirective.getFilters());
expect(fileDropDirective.uploader.addToQueue).toHaveBeenCalledWith(...expectedArguments);
expect(fileOverData).toBeFalsy();
expect(fileDropData).toEqual(uploadedFiles);
});
@@ -144,5 +143,5 @@ function getFakeEventData(): any {
},
preventDefault: () => undefined,
stopPropagation: () => undefined
};
}
}

View File

@@ -2,9 +2,9 @@ import { TestBed, ComponentFixture } from '@angular/core/testing';
import { Component, DebugElement } from '@angular/core';
import { By } from '@angular/platform-browser';
import { FileUploadModule } from '../../file-upload/file-upload.module';
import { FileSelectDirective } from '../../file-upload/file-select.directive';
import { FileUploader } from '../../file-upload/file-uploader.class';
import { FileUploadModule } from '../file-upload/file-upload.module';
import { FileSelectDirective } from '../file-upload/file-select.directive';
import { FileUploader } from '../file-upload/file-uploader.class';
@Component({
selector: 'container',
@@ -54,18 +54,15 @@ describe('Directive: FileSelectDirective', () => {
it('can get uploader options', () => {
const options = fileSelectDirective.getOptions();
expect(options).toBeTruthy();
if (options) {
// Check url set through binding
expect(options.url).toBe(hostComponent.url);
// Check default options
expect(options.autoUpload).toBeFalsy();
expect(options.isHTML5).toBeTruthy();
expect(options.removeAfterUpload).toBeFalsy();
expect(options.disableMultipart).toBeFalsy();
}
// Check url set through binding
expect(options.url).toBe(hostComponent.url);
// Check default options
expect(options.autoUpload).toBeFalsy();
expect(options.isHTML5).toBeTruthy();
expect(options.removeAfterUpload).toBeFalsy();
expect(options.disableMultipart).toBeFalsy();
});
it('can get filters', () => {
@@ -94,6 +91,9 @@ describe('Directive: FileSelectDirective', () => {
fileSelectDirective.onChange();
expect(fileSelectDirective.uploader.addToQueue).toHaveBeenCalledWith(directiveElement.nativeElement.files, fileSelectDirective.getOptions(), fileSelectDirective.getFilters());
const expectedArguments = [ directiveElement.nativeElement.files,
fileSelectDirective.getOptions(),
fileSelectDirective.getFilters() ];
expect(fileSelectDirective.uploader.addToQueue).toHaveBeenCalledWith(...expectedArguments);
});
});

37
src/tsconfig.json Normal file
View File

@@ -0,0 +1,37 @@
{
"compilerOptions": {
"outDir": "../dist",
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": false,
"noEmitHelpers": false,
"noImplicitAny": true,
"declaration": true,
"skipLibCheck": true,
"stripInternal": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"lib": ["dom", "es6"],
"types": [
"jasmine",
"webpack"
],
"typeRoots": [
"../node_modules/@types"
]
},
"exclude": [
"node_modules"
],
"files": [
"../scripts/typings.d.ts",
"./ng2-chunk-file-upload.ts",
"./index.ts"
],
"angularCompilerOptions": {
"genDir": "../temp/factories"
}
}

View File

@@ -1,27 +0,0 @@
{
"compileOnSave": false,
"compilerOptions": {
"rootDir": ".",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"target": "es2015",
"module": "esnext",
"lib": [
"es2017",
"dom"
],
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"baseUrl": ".",
"paths": {
"ng2-file-upload": [
"libs/ng2-file-upload/index.ts"
]
}
},
"exclude": []
}

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": "./node_modules/codelyzer",
"rules": {
"no-forward-ref": false,
"no-null-keyword": false,
"only-arrow-functions": false,
"no-access-missing-member": false,
"directive-selector": false,
"component-selector": false
}
}
"rulesDirectory": [
"node_modules/codelyzer"
],
"rules": {
"trailing-comma": [
true,
{
"multiline": "always",
"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
}
}