1

I am trying to create a download button, which enables the user to download a document from my node.js server.

Here's the fancy button:
enter image description here

I am using Angular as a front-end framework and node.js and express.js for the backend.
enter image description here

This is the document I would like the user to be able to download: enter image description here

So for the backend I wrote this code:

server.js

const bodyParser = require('body-parser');
const cors = require('cors')
const express = require('express');
const app = express();
const router = express.Router();
const path = require('path');

app.use(cors());
app.use(bodyParser.json());


router.route('/generateReportByGet').get((req, res) => {
        res.download(path.join(__dirname, 'docs/doc1.txt'), function (err) {
            if (err) {
                console.log(err);
              } else {
                console.log('%c%s', 'color: #f2ceb6', 'NO ERROR');
                console.log('%c%s', 'color: #00a3cc', res);
              }
        });
});

app.use('/', router);
app.listen(5353, () => console.log('Express server running on port 5353'));

After running the server.js file, and typing:

localhost:5353/generateReportByGet

The file gets downloaded:

enter image description here

So here's what my logic told me:

Create a button with Angular that sends a GET request to that same adress and I should get the same result: The file gets downloaded.

So my first question is : Is my logic flawed?

So here's the front-end code:

app.component.html:

<button  color="primary" (click)="generateReportbyGet()">Generate report By Get</button>
<router-outlet></router-outlet>

app.component.ts:

import { Component } from "@angular/core";
import { GenerateReportService } from "./services/generate-report.service";
@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  constructor(private generateReportService: GenerateReportService) {}
  generateReportbyGet() {
    this.generateReportService.generateReportbyGet().subscribe((results) => {
      console.log("generateReportbyGet ...");
      console.log('%c%s', 'color: #aa00ff', results);
  }
}

generate-report.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
  providedIn: 'root'
})
export class GenerateReportService {
  uri = 'http://localhost:5353';
  constructor(private http: HttpClient) {}
  generateReportbyGet() {
    return this.http.get(`${this.uri}/generateReportByGet`, {responseType: 'text'});
  }
}

I thought this should work as I described. However, when I click on the button nothing happens.
But, on the browser console, I am able to retrieve the text from the file:
enter image description here

So here's my second question:
2/ Why doesn't the file downloading process get started when I click on the button? Is it a problem with the code or the GET request logic?
Thank you!!

2 Answers 2

1

In your Node JS server side code... you're reading the contents of the file and sending them...

(1) to return a file, you can do a:

app.get('/generateReportByGet', function (req, res) { res.sendFile(__dirname + "/" + "docs/doc1.txt"); })

(2) or you can do a (as per this):

app.get('/generateReportByGet', function(req, res){
  const file = `${__dirname}/docs/doc1.txt`;
  res.download(file); 
});
Sign up to request clarification or add additional context in comments.

2 Comments

This also worked :D Could you please make a comparison with the other answer ranjeet has provided and tell me which one you think I should use? :D Thank you
For ranjeet's answer you don't need NodeJS... so if you can construct the full path on client-side, go for it
1

File can't be downloaded making ajax call. In your component service change below code.

generateReportbyGet() {
 var link=document.createElement('a');
    link.href=`${this.uri}/generateReportByGet`;
    link.download="MyDoc.txt";
    link.click();
}

3 Comments

Problem Solved! Thank you <3 But I want to understand how your solution worked. Can you please provide links or what to search exactly to understand it? I don't just want to copy paste :)
You can't download it through Ajax because JavaScript cannot save files directly to a user's computer (out of security concerns). For download attribute visit webdesign.tutsplus.com/tutorials/…
Thanks again. Btw, I think this line " link.download="MyDoc.txt"; " is unecessary.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.