How can I navigate to an external URL parameter?

Viewed 124

So, I've been trying to redirect a URL and open it in a new tab, but I've not been able to do it.

I have an API that's returning me a plain text that's coming as a BLOB object, but actually, it's just a URL. I need to open that URL in a new tab.

This is the code I'm trying to get to work:

    this.printingService.getCvUrl(options).subscribe(
      url => {
        const downloadURL = window.URL.createObjectURL(url);
        window.open(downloadURL, '_blank');
      }
    );

It calls the getCvUrl method, that it's this:

   getCvUrl(options: { remoteUrl: string, paperHeight?: string, paperWidth?: string }): Observable<any> {
    const user = this.authenticationService.getCurrentUser();
    const PRINT_SERVICE = `/api/users/${user.id}/syncMyCV`;
    const CV_SERVICE = 'https://cv.url/template/ce';

    const formData = new FormData();
    formData.append('remoteURL', CV_SERVICE + options.remoteUrl);
    formData.append('paperHeight', options.paperHeight);
    formData.append('paperWidth', options.paperWidth);

    const token = this.authenticationService.getToken();

    return this.http.post(
      PRINT_SERVICE,
      formData,
      {
        headers: {
          'Anonymous': 'undefined',
          'accept': '*/*',
          'Authorization': token
        },
        responseType: 'blob'
      }
    ).pipe(catchError(err => {
      this.errorService.handleError(err);
      return observableOf(null);
    }));
  }

As a response, this is currently opening a new tab for me, with the text of the URL as content, but not in the browser's URL field.

I've tried all of these approaches:

First I tried navigating with the router, but of course, it didn't work, as I'm trying to open an external URL.

    this.printingService.getCvUrl(options).subscribe(
      url => this.router.navigate([url])
    );

Then, looking at some of the questions, I tried to modify the href attribute of the window location. It didn't work either

    this.printingService.getCvUrl(options).subscribe(
      url => window.location.href = url
    );

Then, following another answer, I changed to the window open method, and it opened a new tab, but then there was giving me a 404 error

    this.printingService.getCvUrl(options).subscribe(
      url => window.open(url, '_blank')
    );

After looking over it, I realized I was trying to redirect a blob object as if it was a URL string, so some conversion was needed. Then I tried using a method I created in the same service I'm using.

    this.printingService.getCvUrl(options).subscribe(
      url => {
        this.printingService.view(url);
      }
    );

And then it called the view() method in the printing service, which is implemented as follows:

    view(data: ArrayBuffer, filename = 'resume.pdf') {
    if (!!data) {
      const blob = new Blob([data], {type: 'application/pdf'});
      const downloadURL = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = downloadURL;
      link.download = filename;
      link.click();
    }
  }

But the problem is that this method downloads a pdf, but it's not even what I want, so I decided to take what I need from that method, and adapt it. Then I got to the current solution above, which is not working either:

    this.printingService.getCvUrl(options).subscribe(
      url => {
        const downloadURL = window.URL.createObjectURL(url);
        window.open(downloadURL, '_blank');
      }
    );

Up to this point, I ran out of ideas. Does anyone have any other approach I have not tried?


Solution using the accepted answer:

In the getCvUrl method, I changed this line:

responseType: 'blob'

by this:

responseType: 'text'

as the answer coming from the API will always be a text/plain response. And the final code looks like this:

    this.printingService.getCvUrl(options).subscribe(
      url => {
        const downloadLink = document.createElement('a');
        downloadLink.href = url;
        document.body.appendChild(downloadLink);
        downloadLink.click();
        document.body.removeChild(downloadLink);
      }
    );
2 Answers

I am not sure if this will work, but try adding the link element to the DOM before clicking it and then remove it.

function openBlob(data: Blob) {
  //Add a link and click it!
  const downloadLink = document.createElement("a");
  downloadLink.href = window.URL.createObjectURL(data);
  downloadLink.download = filename;
  document.body.appendChild(downloadLink);
  downloadLink.click();
  document.body.removeChild(downloadLink);
}

try with this package file-saver

it's easy to implement.

import { saveAs } from 'file-saver';

 this.http
  .post(
    yourURL
    {
      responseType: 'arraybuffer',
    }
  )
  .subscribe((val: any) => {
    const blob = new Blob([val], { type: 'application/pdf' });
    const url = window.URL.createObjectURL(blob);
    saveAs(blob, 'name.pdf');
  });
Related