Filesaver.js: Help needed in using fileSaver.js with Angular 2 app

Created on 13 Feb 2017  路  41Comments  路  Source: eligrey/FileSaver.js

I am trying to use fileSaver.js with angular 2 , but am not able to import the module

i am getting cannot find file-saver module error .

Any help is appreciated

Most helpful comment

import * as FileSaver from 'file-saver';

FileSaver.saveAs(blob, fileName);

All 41 comments

This is how I got it to run in my Angular 2 project.

Ran npm install file-saver --save

Then I only had to include import { saveAs } from 'file-saver'; at the top of the file of where I'm calling the save function. You may need to upgrade your TypeScript version to the latest to be able to import.

In your typescript code you can call saveAs with saveAs(new Blob([data], { type: "text" }), 'data.txt');.

If you want typescript data typing you can load @types/file-saver.

@Chris3773 I installed the latest typescript but it still won't import saveAs, I get this error:
Cannot find module 'file-saver'.. It is it node_modules. I'm using webpack could that cause this issue?

I know this will work for webpack version 2.2.0 and awesome-typescript-loader version 3.0.4.

You could also check your tsconfig.json and make sure it's set to node "moduleResolution": "node".

@Chris3773 I made sure I met all those requirements, my error message changed to this now: [at-loader] src/app/lib/api.ts:8:24 TS2307: Cannot find module 'file-saver'.

This is my package.js

  "dependencies": {
    "@angular/common": "4.0.0-beta.0",
    "@angular/compiler": "4.0.0-beta.0",
    "@angular/compiler-cli": "4.0.0-beta.0",
    "@angular/core": "4.0.0-beta.0",
    "@angular/forms": "^4.0.0-beta.0",
    "@angular/http": "4.0.0-beta.0",
    "@angular/platform-browser": "4.0.0-beta.0",
    "@angular/platform-browser-dynamic": "4.0.0-beta.0",
    "@angular/platform-server": "4.0.0-beta.0",
    "@angular/router": "4.0.0-beta.0",
    "@ng-bootstrap/ng-bootstrap": "^1.0.0-alpha.15",
    "@swimlane/ngx-charts": "^3.1.0",
    "@swimlane/ngx-datatable": "^4.1.0",
    "angular-2-local-storage": "^1.0.0",
    "awesome-typescript-loader": "^3.0.7",
    "bootstrap": "^4.0.0-alpha.5",
    "bootstrap-loader": "2.0.0-beta.17",
    "core-js": "^2.4.1",
    "file-saver": "^1.3.3",
    "font-awesome": "^4.6.3",
    "jquery": "^3.1.1",
    "lodash": "^4.17.2",
    "moment": "^2.17.1",
    "ng2-file-upload": "^1.1.4-2",
    "ng2-restangular": "^0.1.23",
    "ng2-validators": "^1.6.1",
    "ngx-uploader": "^2.0.22",
    "reflect-metadata": "^0.1.8",
    "rxjs": "^5.0.1",
    "tether": "^1.3.8",
    "zone.js": "^0.7.2"
  },
  "devDependencies": {
    "@types/core-js": "^0.9.34",
    "@types/jasmine": "^2.5.38",
    "@types/jquery": "^2.0.32",
    "@types/lodash": "^4.14.41",
    "@types/node": "^6.0.52",
    "@types/protractor": "^4.0.0",
    "@types/selenium-webdriver": "^2.53.36",
    "angular-2-dropdown-multiselect": "^0.4.0",
    "angular2-template-loader": "^0.6.0",
    "autoprefixer": "^6.5.4",
    "awesome-typescript-loader": "^3.0.7",
    "bower-webpack-plugin": "^0.1.9",
    "browser-sync": "^2.18.5",
    "browser-sync-webpack-plugin": "^1.1.3",
    "chunk-manifest-webpack-plugin": "^1.0.0",
    "codelyzer": "2.0.0-beta.1",
    "compression-webpack-plugin": "^0.3.2",
    "copy-webpack-plugin": "^4.0.1",
    "copyfiles": "^1.0.0",
    "css-loader": "^0.26.0",
    "d3": "^4.6.0",
    "exports-loader": "^0.6.3",
    "extract-text-webpack-plugin": "2.0.0-beta.4",
    "font-awesome-sass-loader": "^1.0.2",
    "fontawesome": "^4.7.0",
    "html-loader": "^0.4.4",
    "html-webpack-plugin": "^2.24.1",
    "inline-manifest-webpack-plugin": "^3.0.1",
    "istanbul-instrumenter-loader": "^1.1.0",
    "jasmine-core": "^2.5.2",
    "json-loader": "^0.5.4",
    "karma": "^1.3.0",
    "karma-chrome-launcher": "^2.0.0",
    "karma-coverage": "^1.1.1",
    "karma-firefox-launcher": "^1.0.0",
    "karma-jasmine": "^1.1.0",
    "karma-jasmine-diff-reporter": "^0.6.3",
    "karma-jasmine-html-reporter": "^0.2.2",
    "karma-mocha-reporter": "^2.2.1",
    "karma-phantomjs-launcher": "^1.0.2",
    "karma-remap-coverage": "^0.1.3",
    "karma-sourcemap-loader": "^0.3.7",
    "karma-webpack": "^1.8.0",
    "lite-server": "^2.2.2",
    "mkdirp": "^0.5.1",
    "node-sass": "^4.0.0",
    "node-static": "^0.7.8",
    "null-loader": "^0.1.1",
    "phantomjs-prebuilt": "^2.1.14",
    "postcss-loader": "^1.2.1",
    "protractor": "^4.0.13",
    "raw-loader": "^0.5.1",
    "remap-istanbul": "0.8.0",
    "resolve-url-loader": "^1.6.1",
    "rimraf": "^2.5.4",
    "rxjs": "^5.2.0",
    "sass-loader": "^4.0.2",
    "style-loader": "^0.13.1",
    "to-string-loader": "^1.1.5",
    "ts-helpers": "^1.1.2",
    "ts-loader": "^1.3.2",
    "ts-node": "^1.7.2",
    "tslint": "^4.4.2",
    "tslint-loader": "^3.2.0",
    "typescript": "2.0.10",
    "url-loader": "^0.5.7",
    "webpack": "^2.2.0-rc.2",
    "webpack-dev-server": "^2.2.0-rc.0",
    "webpack-manifest-plugin": "^1.1.0",
    "webpack-md5-hash": "^0.0.5",
    "webpack-merge": "^1.1.1"
  }

and my tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false,
    "typeRoots": [
      "node_modules/@types"
    ]
  },
  "exclude": [
    "node_modules",
    "coverage",
    "config",
    "report",
    "**/*.spec.ts"
  ],

  "awesomeTypescriptLoaderOptions": {
    "useWebpackText": true
  },

  "compileOnSave": false,
  "buildOnSave": false,
  "atom": { "rewriteTsconfig": false }
}

Hi @Chris3773

I got this error:
file_saver_1.saveAs is not a function, can you help me?

Here is my environment:

Angular version: 2.4.3, 
"typescript": "2.1.5", 
"@types/file-saver": "0.0.0",

In tsconfig.json, set to node "moduleResolution": "node".
In systemjs.config.js, 'file-saver': 'node_modules/file-saver/FileSaver.js'

In my html file:
<img (click)="downloadFile()" src="download-icon.jpeg">

In my ts file:

import { saveAs } from "file-saver";

public downloadFile(): void {
     console.log(saveAs);  // I got "undefined" from console
     saveAs(new Blob(['hello world'], { type: "text" }), 'data.txt');
}

I have exact the same problem with same configuration.

I found a workaround:

removed the import statement on top of my component and then:

let saveAs = require('file-saver');
let file = new Blob([data], { type: 'text/csv;charset=utf-8' });
saveAs(file, 'helloworld.csv');

No idea why this is working...

you need to install the typescript definitions. npm install @types/file-saver --save
it worked for me

@Chris3773 your solutions works with angular cli project, can you please guide what setting would e required for systemjs.config.js ? I added

'file-saver': 'node_modules/file-saver/FileSaver.js',

to map, but its not working.

I have the same problem, @HeinzBiglerCMI code solved it.
The code that is generated when using Typescript+Angular mentioned by @junjunruan is the following:

var file_saver_1 = require('file-saver');
file_saver_1.saveAs(...)

Which is obviously different from the code above that works, but it is the code the readme.md file is saying it should work with require so I'm not sure why it doesn't...

import * as FileSaver from 'file-saver';

FileSaver.saveAs(blob, fileName);

The above options did not work for me - wither it failed during bundling with systemjs-builder or later at runtime. The only thing that worked was using require as shown by @HeinzBiglerCMI

Since I wanted to stick to TS imports and not use require directly, this is the working solution I ended up with:

tsconfig.json
"target" : "es5", "module" : "commonjs", "moduleResolution" : "node"

package.json
"file-saver" : "1.3.3", "@types/file-saver" : "0.0.1"

systemjs.config.js

map: {
    'file-saver': 'npm:file-saver'
},
packages: {
    'file-saver': {
        format: 'global',
        main: 'FileSaver.js',
        defaultExtension: 'js'
    }
}

component.ts

import 'file-saver';
... and then calling later in function ...
var blob = new Blob([data.blob()], {type: 'my-content-type'});
saveAs(blob, 'fileName.xyz');

this issue is pretty wierd, on my case this is already installed

package.json
"@types/file-saver" : "0.0.1"

so I tried to install npm install file-saver --save, I hope there is a way if I install @types/file-saver it will also install the js version.

The solution by @tarmo-randma worked for me, specifically adding

format: 'global',

to the SystemJS config.

I'm using SystemJS and I've tried different solutions, but only this one worked for me:

package.json

"devDependencies": {
"@types/file-saver": "^0.0.1",
},
"dependencies": {
"@angular/core": "^4.4.4",
"file-saver": "^1.3.3",
}

tsconfig.json

"typeRoots": [
      "../../node_modules/@types",
      "../../node_modules"
    ],
    "types": [
      "file-saver"
    ]

SystemJS config

'file-saver': 'node_modules/file-saver/FileSaver.min.js'

component.ts

import { ResponseContentType } from '@angular/http';

declare var saveAs: any;

this.http.get('testurl', {responseType: ResponseContentType.Blob})
      .map(
        (res) => {
          return new Blob([res.blob()], {type: 'application/pdf'});
        })
      .subscribe(
        (blob: Blob) => {
          saveAs(blob, 'testFile.pdf');
        }
      );

I use Angular 5 and I have same problem:

tsconfig.json
"target" : "es5", "strict" : true, "moduleResolution" : "node"

package.json
"file-saver" : "1.3.3", "@types/file-saver" : "1.3.2"

ERROR in C:/workspace/POC/filesave-angular4-example/angular-frontend/src/app/app.component.ts (4,24): Could not find a declaration file for module 'file-saver/FileSaver'. 'C:/workspace/POC/filesave-angular4-example/angular-frontend/node_modules/file-saver/FileSaver.js' implicitly has an 'any' type.

ERROR in C:/workspace/POC/filesave-angular4-example/angular-frontend/src/app/app.component.ts (4,24): Could not find a declaration file for module 'file-saver/FileSaver'. 'C:/workspace/POC/filesave-angular4-example/angular-frontend/node_modules/file-saver/FileSaver.js' implicitly has an 'any' type.

Is this still an issue after the latest updates?

@Ruffio I just tried it today, got the same issue.

The only way around it for me was @tarmo-randma 's suggestion

Fix: npm install [email protected] --save
The FileSaver.saveAs method is not supported in the 1.3.4 newer version of file saver

@r-paredes-bernal Thank you!!
Well, I don't know what's called "breaking changes" these days but I vote for this one.

I just run: npm install --save @types/file-saver

I am using angular 6 + FileSaver. I needed to download PDF from server. Here is what worked:

npm install file-saver --save

import { saveAs } from 'file-saver';

package.json:

"file-saver": "^1.3.8"

 this.http
      .get<any>("/pdfs/mypdf.pdf", { responseType: 'blob' as 'json' })
      .pipe(
        tap(deployments => this.log(`fetched resoure`)),
        catchError(this.handleError('getResource', []))
      )
      .subscribe(data => {
        console.log(data);
        saveAs(new Blob([data], { type: 'pdf' }), 'data.pdf');
      });

@nitinja this type assertion looks plain wrong to me:

responseType: 'blob' as 'json'

Instead, I would declare a variable of type any to bypass the type checks and pass the variable to get() as second argument:

const options: any = ({
     responseType : 'blob'
   }
);

this.http
      .get<any>("/pdfs/mypdf.pdf", options)

@elion I tried only 'blob' and it did not work for me (though I agree mine is more of a hack). I will try your suggestion, thanks.

i tryied this code but have that error can not get file

  const headers = new Headers({
      'Content-Type': 'application/json',
      'Accept': 'application/pdf'
    });
    const options = new RequestOptions({headers: headers});
    options.responseType = ResponseContentType.Blob;



    this.http.post('./ng-book2-angular-6-r68.pdf', '', '').map((response) => {
      console.log('asdsadsad');
      const blob = response.blob();
      const filename = 'ng-book2-angular-6-r68.pdf';
      FileSaver.saveAs(blob, filename);
    });

Can this works for multiple files selected.
Can we zip these files at client -side.
Does it work on all browser. I did try in safari. some issues of security.
Does it work with binary files.

Can this works for multiple files selected.
Depends on browser

Can we zip these files at client -side.
Yes

Does it work on all browser. I did try in safari. some issues of security.
Should be working

Does it work with binary files.
Yes

Would give more proper answer but I'm on a phone

I am looking at this example.

This example for one file download.

headers.append('Accept', 'text/plain');
headers.append('Access-Control-Allow-Origin', '*');

In order to test

ccess to XMLHttpRequest at 'http://192.168.4.1/ebl_data_logs/EBL000013/099_20190518_111653.ebl' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Seems like the file is coming from a server?
Can't you just use Content-Disposition attachment header instead to save the file instead of using FileSaver?

No sure what you mean. give example typescript code.

Ho can pipe multiple HTTP get file request sequential. I do not want to send simulations HTTP get request. I have list of URLs for each file to download. how can I pipe in sequential to down file by file programmatically.

No sure what you mean. give example typescript code.

Nope. It's server side code - I don't know what stack you are using koa, express, uws... deno or node

zip all files on the server and then give that to the user?

I want to download multiple files using http get file. I know urls of all selected file.

FileSave for blob is not working for it. I can trigger hyper link click.

I need to download file by file. one a t time.

http.getFile(url).subscribe(blob => {
  document.getElementById(file_name).click();
}, errmsg => {

});

Okey, if you insist in using multiple url's and not do it on the server side... wish i recommend

have a look at some of this tools:

if you go with the StreamSaver route, then i think Angular's http client isn't a good candidate to handle ajax as you would need the ReadableStream from the response object

es7

const urls = [
  'https://httpbin.org/get'
].values()

new ZIP({
  async pull (ctrl) {
    const it = urls.next()
    if (it.done) {
      ctrl.close()
    } else {
      const res = await fetch(it.value)
      const stream = () => res.body
      const name = `/folder/foo-${Math.random()}.bin`
      ctrl.enqueue({ name, stream })
    }
  }
}).pipeTo(streamSaver.createWriteStream('archive.zip'))

es6

new ZIP({
  pull (ctrl) {
    const it = urls.next()
    if (it.done) {
      ctrl.close()
    } else {
      return fetch(it.value).then(res => {
        const stream = () => res.body
        const name = `/folder/foo-${Math.random()}.bin`
        ctrl.enqueue({ name, stream })
      })
    }
  }
})

Thanks for example. I appreciate. this is JS example. I am using angular 2x/cli TypeScript. Any example for TypeScript. Can I use JS within my angular 2.x code.

I am using angular 2x/cli TypeScript. Any example for TypeScript. Can I use JS within my angular 2.x code.

The fact that you are asking this question seems very ....

TypeScript is a superset of javascript and any javascript can be used in typescript but not the other way around.
You should be able to understand and convert any javascript to typescript if you like.
You should most definitely learn JavaScript before learning TypeScript
You should learn the language before using any framework too

Sorry for asking basic question. I am not expert in JS.
I learned JS/angular 1.x and used before. It looks to be some work either to write JS code as typescript code or use JS within my TypeScript angular application. I will try later.

If you have time. Do help me with example code to use above JS code which download and zip it as part of simple TypeScript/Angular as example.

new ZIP

Uncaught ReferenceError: ZIP is not defined

I have tried including all these JS.

<script src="../node_modules/streamsaver/StreamSaver.js"></script>
<script src="../node_modules/jszip/dist/jszip.js"></script>
<script src="./zip.js/WebContent/zip.js"></script>
<script src="./zip-stream.js"></script>

Then you have probably not included zip-stream.js properly? do you get 404 when loading the file?

try new window.ZIP if that helps

And why load both zip stream and zip.js?

I managed to use file saver.

https://www.npmjs.com/package/ngx-filesaver

It is working except on safari web browser on apple device.

The FileSaver.saveAs method is not supported in the 1.3.4 newer version of file saver

Thanks, it works for me!

"file-saver" : "1.3.3"

where can i find SystemJS config file?? there is no such file in my project

Was this page helpful?
0 / 5 - 0 ratings

Related issues

HeroSony picture HeroSony  路  5Comments

ezequiel88 picture ezequiel88  路  4Comments

binishprabhakar picture binishprabhakar  路  6Comments

rhyous picture rhyous  路  6Comments

Toterbiber picture Toterbiber  路  5Comments