在TypeScript(Angular)中打开下载链接

4
我的问题很简单。我有一个使用Angular构建的接口,如此处所示。当我点击1时,它会打开弹出窗口,然后当我点击2时,它将调用一个函数。请帮我翻译一下。
showDownloadLink(ev, name) {
    let config = new MdDialogConfig()
        .textContent('<a href="http://www.google.fr">lol</a>')
        .clickOutsideToClose(false)
        .title('Would you like to delete your debt?')
        .ariaLabel('Lucky day')
        .ok('Please do it!')
        .cancel('Sounds like a scam')
        .targetEvent(ev);
    this.dialog.open(MdDialogBasic, this.element, config)
        .then((ref: MdDialogRef) => {
            ref.whenClosed.then((result) => {
                if (result) {
                    var url = this._Service.getDownloadLink(name);
                    console.log(url);
                    //window.open(url,'Download');
                    //this.downloadURI(url );
                }
                else {
                    this.status = 'You decided to keep your debt.';
                }
            })
        });
}

downloadURI(uri) {
    var link = document.createElement("a");
    link.href = uri;
    link.click();
}

所使用的模块是ng2-material,其中包含“确认对话框”按钮。

当单击控制台中显示的链接时,变量url会在控制台中输出一个良好的URLconsole.log(url); =>,它可以正常下载文件 :)

问题在于下载没有在代码中触发。

编辑1:

移动了一些东西后-

Dashboard.components.ts:

downloadFile(url,file) {
    this._Service.getDownloadFile(url,file);
}

在之前的代码中,show download链接中调用了downloadFile函数。

在_service.ts文件中:

import {Injectable} from "angular2/core";
import {S3Object} from "./s3object";
import {Observable} from "rxjs/Observable";
import {Http, Headers, Response} from "angular2/http";
import "rxjs/Rx";
import {CredService} from "./cred.service";
//mettre les parenthèses !!
@Injectable()
export class Service {

    private serviceUrl = 'url';
    private token;
    private headers = new Headers();
    private credS;

    constructor(private http:Http, private cred:CredService) {
        this.credS = cred;
        this.token = cred.getToken();
        this.headers.append('Authorization', 'bearer ' + this.token);
        this.headers.append('Content-Type', 'application/json');
    }

    getDownloadLink(path:string){
        var opUrl = 'download.json?objectKey='+path;
        var urlRes = "";
        this.http.get(
            this.serviceUrl + opUrl,
            { headers: this.headers }
        )
            .map(res => res.text())
            .subscribe(
                data => urlRes = data,
                err => console.log(err),
                () => console.log(urlRes)
            );

        //console.log(urlRes);
        return urlRes;
    }

    getDownloadFile(url:string, file:string) {
        this.http.get(url).subscribe(
            (response) => {
                var blob = new Blob([response._body], {type: "application/text"});
                var filename = file;
                saveAs(blob, filename);
            });
    } 
}

还有一个customBrowserXhr.ts文件:

import {Injectable} from 'angular2/core';
import {BrowserXhr} from 'angular2/http';

@Injectable()
export class CustomBrowserXhr extends BrowserXhr {
    constructor() {}
    build(): any {
        let xhr = super.build();
        xhr.responseType = "blob";
        console.log("it's cool bro ! ");
        return <any>(xhr);
    }
}

编辑2:

我的函数执行的控制台日志(我在代码中用URL替换了正确的网址)

test url ddl before : "URL/Desert.jpg?serieofparams"
test name ddl before : Desert.jpg

这个函数:

downloadFile(url,file) {
    console.log('test url ddl before : ' + url);
    console.log('test name ddl before : ' + file);
    this.http.get(url).subscribe(
        (response) => {
            var blob = new Blob([response._body], {type: "image/jpeg"});
            var filename = file;
            saveAs(blob, filename);
        });
}

但是我遇到了这个错误:
Failed to load resource: the server responded with a status of 404 (Introuvable) http://localhost:8080/context/%22URL/Desert.jpg?serieofparams%22
angular2.dev.js:23740 EXCEPTION: [object Object]

有人知道是什么原因导致这个问题吗? 路由模块是否会引起这种情况? 在这个 Plunkr 上它正常运行。


如何允许下载多种类型的文件,例如pdf、lpg、png {type: "image/jpeg"} - user2180794
2个回答

2

一种方法是通过 AJAX 请求加载图像,然后利用 FileSaver 库打开下载对话框。

这里是一个示例。您需要扩展 BrowserXhr 类来设置响应类型。

@Injectable()
export class CustomBrowserXhr extends BrowserXhr {
  constructor() {}
  build(): any {
    let xhr = super.build();
    xhr.responseType = "blob";
    return <any>(xhr);
  }
}

然后您可以利用这个类执行请求以获取图像内容:
@Component({
  selector: 'download',
  template: `
    <div (click)="downloadFile() ">Download</div>
  `,
  providers: [
    provide(CustomBrowserXhr, 
      { useClass: CustomBrowserXhr }
  ]
})
export class DownloadComponent {
  @Input()
  filename:string;

  constructor(private http:Http) {
  }

  downloadFile() {
    this.http.get(
      'https://mapapi.apispark.net/v1/images/'+this.filename).subscribe(
        (response) => {
          var mediaType = 'application/pdf';
          var blob = new Blob([response._body], {type: mediaType});
          var filename = 'test.pdf';
          saveAs(blob, filename);
        });
    }
}

这个覆盖(设置响应类型)仅适用于此组件(不要忘记在引导您的应用程序时删除相应的提供程序),因为我在组件的providers属性中设置了提供程序。下载组件可以像这样使用:

@Component({
  selector: 'somecomponent',
  template: `
    <download filename="'Granizo.pdf'"></download>
  `
  , directives: [ DownloadComponent ]
})

请参考以下回答获取更多细节:


我正在研究它,即使我不太理解这个可能的解决方案。 - Slater
是的,但您需要从响应的“Content-Type”标头中提取类型... - Thierry Templier
我在 build() 函数中添加了这行代码:console.log("it's cool bro ! ");当下载启动时,控制台没有显示任何消息...我猜测这是因为自定义类没有真正被使用...在 main.ts 中,我有以下代码: bootstrap(AppComponent, [ROUTER_PROVIDERS,HTTP_PROVIDERS,provide(BrowserXhr, { useClass: CustomBrowserXhr })]); - Slater
你在执行HTTP请求的组件的providers属性中指定了它的提供程序吗? - Thierry Templier
是的,这很正常,因为它在“subscribe”方法中定义的回调之外...您应该在服务之外订阅。 - Thierry Templier
显示剩余13条评论

0
简单的解决方案是使用“getDownloadLink”返回中间链接,该链接将重定向用户到您想要的实际链接。
var url = this._Service.getDownloadLink(name);
console.log(url);
window.location = url;

请注意,在实际的下载链接中,从服务器端您需要设置适当的内容配置头。

那个解决方案不起作用。在我的情况下,它只会使页面在同一位置刷新,而不会启动任何下载。 - Slater

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接