使用AngularJS的ASP.NET Web API方法下载文件 [英] Download file from an ASP.NET Web API method using AngularJS

查看:288
本文介绍了使用AngularJS的ASP.NET Web API方法下载文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的角度JS的项目,我有一个< A> 锚标记,点击后使其中HTTP GET 请求返回一个文件的WebAPI方法。

现在,我想一旦请求是成功的文件被下载到用户。我该怎么做呢?

锚标记:

 < A HREF =#NG点击=getthefile()>下载IMG< / A>

AngularJS:

  $ scope.getthefile =功能(){
    $ HTTP({
        方法:GET,
        缓存:假的,
        网址:$ scope.appPath +'CourseRegConfirm / GETFILE',
        标题:{
            内容类型:应用/ JSON的;字符集= UTF-8
        }
    })。成功(功能(数据,状态){
        的console.log(数据); //显示文本数据,如果该文件是一个文本文件,二进制如果它是一个形象
        //我应该写在这里下载我来自的WebAPI方法接收文件?
    })错误(功能(数据,状态){
        // ...
    });
}

我的WebAPI方式:

[授权]
[路线(GETFILE)]
公众的Htt presponseMessage GetTestFile()
{
    HTT presponseMessage结果= NULL;
    变种localFilePath = HttpContext.Current.Server.MapPath(〜/ timetable.jpg);    如果(!File.Exists(localFilePath))
    {
        结果= Request.CreateResponse(的HTTPStatus code.Gone);
    }
    其他
    {
        //文件即成到客户端
        结果= Request.CreateResponse(的HTTPStatus code.OK);
        result.Content =新StreamContent(新的FileStream(localFilePath,FileMode.Open,FileAccess.Read));
        result.Content.Headers.ContentDisposition =新System.Net.Http.Headers.ContentDispositionHeaderValue(附件);
        result.Content.Headers.ContentDisposition.FileName =SampleImg;
    }    返回结果;
}


解决方案

在用ajax下载二进制文件的支持也不是很大,这还很多的下的发展作为工作草案的。

简单下载方式:

您可以让浏览器只需使用下面的code下载所需的文件,这是在所有的浏览器都支持,而且显然会引发的WebAPI的要求是一样的。

$ scope.downloadFile =功能(downloadPath){
    window.open(downloadPath,'_blank','');
}

阿贾克斯二进制下载方式:

使用AJAX下载二进制文件可以在某些浏览器进行以下是将在Chrome,IE浏览器,Firefox和Safari的最新口味工作的实现。

它使用 arraybuffer 响应类型,然后将其转换成一个JavaScript 一滴,它是那么无论presented使用 saveBlob 方法保存 - 虽然这只是目前present在Internet Explorer - 或者变成它是由浏览器中打开一个BLOB数据的URL,触发下载对话框如果MIME类型支持查看在浏览器中。

的Internet Explorer 11的支持(固定)

注:Internet Explorer的11不喜欢使用 msSaveBlob 功能,如果它已经别名 - 也许是一个安全功能,但更可能的缺陷,因此,使用 VAR saveBlob = navigator.msSaveBlob || 。navigator.webkitSaveBlob ...等来确定可用的 saveBlob 支持出现异常;因此,为什么下面现在code测试为 navigator.msSaveBlob 分开。谢谢?微软

//基于此实现:web.student.tuwien.ac.at/~e0427417/jsdownload.html
$ scope.downloadFile =功能(httpPath){
    //使用一个arraybuffer
    $ http.get(httpPath,{responseTyp的:arraybuffer'})
    .success(功能(数据,状态,标题){        VAR octetStreamMime ='应用程序/八位字节流;
        VAR成功= FALSE;        //获取标题
        头=头();        //从x文件名头或默认为download.bin获取文件名
        变种文件名=标题['X-文件名'] || download.bin';        //确定从标题或默认为application /八位字节流内容类型
        VAR的contentType =标题['内涵式'] || octetStreamMime;        尝试
        {
            //尝试使用msSaveBlob如果支持
            的console.log(试图saveBlob方法...);
            VAR BLOB =新的Blob([数据] {类型:contentType中});
            如果(navigator.msSaveBlob)
                navigator.msSaveBlob(BLOB,文件名);
            其他{
                //尝试使用其他saveBlob实现,如果有的话
                VAR saveBlob = navigator.webkitSaveBlob || navigator.mozSaveBlob || navigator.saveBlob;
                如果(saveBlob ===未定义)抛出不支持;
                saveBlob(BLOB,文件名);
            }
            的console.log(saveBlob成功);
            成功= TRUE;
        }赶上(前)
        {
            的console.log(saveBlob方法失败,出现以下异常:);
            的console.log(除息);
        }        如果(!成功)
        {
            //获取BLOB网址制作
            VAR urlCreator = window.URL || window.webkitUR​​L || window.mozURL || window.msURL;
            如果(urlCreator)
            {
                //尝试使用下载链接
                VAR链接=使用document.createElement('A');
                如果(在链接'下载')
                {
                    //尝试模拟点击
                    尝试
                    {
                        // prepare一个blob网址
                        的console.log(试图用模拟点击下载链接的方法......);
                        VAR BLOB =新的Blob([数据] {类型:contentType中});
                        VAR URL = urlCreator.createObjectURL(BLOB);
                        link.setAttribute('href属性,URL);                        //设置下载属性(支持在Chrome 14+ /火狐20+)
                        link.setAttribute(下载,文件名);                        //模拟点击下载链接
                        VAR事件= document.createEvent('MouseEvents');
                        event.initMouseEvent('点击',真的,真的,窗口,1,0,0,0,0,假的,假的,假的,假的,0,NULL);
                        link.dispatchEvent(事件);
                        的console.log(用模拟点击下载链接方法成功);
                        成功= TRUE;                    }赶上(前){
                        的console.log(用模拟点击下载链接的方法失败,出现以下异常:);
                        的console.log(除息);
                    }
                }                如果(!成功)
                {
                    //回退到window.location的方法
                    尝试
                    {
                        // prepare一个blob网址
                        使用了window.location时强制下载//使用应用程序/八位字节流
                        的console.log(尝试下载链接法window.location的......);
                        VAR BLOB =新的Blob([数据] {类型:octetStreamMime});
                        VAR URL = urlCreator.createObjectURL(BLOB);
                        window.location的= URL;
                        的console.log(与window.location的下载链接方法成功);
                        成功= TRUE;
                    }赶上(前){
                        的console.log(下载链接的方法与window.location的失败,出现以下异常:);
                        的console.log(除息);
                    }
                }            }
        }        如果(!成功)
        {
            //回退到window.open方法
            的console.log(无工作方法用于保存arraybuffer,用最后一招window.open);
            window.open(httpPath,'_blank','');
        }
    })
    .error(功能(数据,状态){
        的console.log(请求失败,状态:+状态);        //选择写错误出范围
        $ scope.errorDetails =请求与状态失败:+状态;
    });
};

用法:

VAR downloadPath =/files/instructions.pdf;
$ scope.downloadFile(downloadPath);

注:

您应该修改您的WebAPI方法返回下列头:


  • 我已经使用了 X-文件名头发送的文件名。这是为了方便自定义标题,你可以使用常规的前pressions但是从中提取内容处置头名。


  • 您应该设置内容类型的MIME头为你的反应了,所以浏览器知道的数据格式。


我希望这有助于。

In my Angular JS project, I've an <a> anchor tag, which when clicked makes an HTTP GET request to a WebAPI method that returns a file.

Now, I want the file to be downloaded to the user once the request is successful. How do I do that?

The anchor tag:

<a href="#" ng-click="getthefile()">Download img</a>

AngularJS:

$scope.getthefile = function () {        
    $http({
        method: 'GET',
        cache: false,
        url: $scope.appPath + 'CourseRegConfirm/getfile',            
        headers: {
            'Content-Type': 'application/json; charset=utf-8'
        }
    }).success(function (data, status) {
        console.log(data); // Displays text data if the file is a text file, binary if it's an image            
        // What should I write here to download the file I receive from the WebAPI method?
    }).error(function (data, status) {
        // ...
    });
}

My WebAPI method:

[Authorize]
[Route("getfile")]
public HttpResponseMessage GetTestFile()
{
    HttpResponseMessage result = null;
    var localFilePath = HttpContext.Current.Server.MapPath("~/timetable.jpg");

    if (!File.Exists(localFilePath))
    {
        result = Request.CreateResponse(HttpStatusCode.Gone);
    }
    else
    {
        // Serve the file to the client
        result = Request.CreateResponse(HttpStatusCode.OK);
        result.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
        result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
        result.Content.Headers.ContentDisposition.FileName = "SampleImg";                
    }

    return result;
}

解决方案

Support for downloading binary files in using ajax is not great, it is very much still under development as working drafts.

Simple download method:

You can have the browser download the requested file simply by using the code below, and this is supported in all browsers, and will obviously trigger the WebApi request just the same.

$scope.downloadFile = function(downloadPath) { 
    window.open(downloadPath, '_blank', '');  
}

Ajax binary download method:

Using ajax to download the binary file can be done in some browsers and below is an implementation that will work in the latest flavours of Chrome, Internet Explorer, FireFox and Safari.

It uses an arraybuffer response type, which is then converted into a JavaScript blob, which is then either presented to save using the saveBlob method - though this is only currently present in Internet Explorer - or turned into a blob data URL which is opened by the browser, triggering the download dialog if the mime type is supported for viewing in the browser.

Internet Explorer 11 Support (Fixed)

Note: Internet Explorer 11 did not like using the msSaveBlob function if it had been aliased - perhaps a security feature, but more likely a flaw, So using var saveBlob = navigator.msSaveBlob || navigator.webkitSaveBlob ... etc. to determine the available saveBlob support caused an exception; hence why the code below now tests for navigator.msSaveBlob separately. Thanks? Microsoft

// Based on an implementation here: web.student.tuwien.ac.at/~e0427417/jsdownload.html
$scope.downloadFile = function(httpPath) {
    // Use an arraybuffer
    $http.get(httpPath, { responseType: 'arraybuffer' })
    .success( function(data, status, headers) {

        var octetStreamMime = 'application/octet-stream';
        var success = false;

        // Get the headers
        headers = headers();

        // Get the filename from the x-filename header or default to "download.bin"
        var filename = headers['x-filename'] || 'download.bin';

        // Determine the content type from the header or default to "application/octet-stream"
        var contentType = headers['content-type'] || octetStreamMime;

        try
        {
            // Try using msSaveBlob if supported
            console.log("Trying saveBlob method ...");
            var blob = new Blob([data], { type: contentType });
            if(navigator.msSaveBlob)
                navigator.msSaveBlob(blob, filename);
            else {
                // Try using other saveBlob implementations, if available
                var saveBlob = navigator.webkitSaveBlob || navigator.mozSaveBlob || navigator.saveBlob;
                if(saveBlob === undefined) throw "Not supported";
                saveBlob(blob, filename);
            }
            console.log("saveBlob succeeded");
            success = true;
        } catch(ex)
        {
            console.log("saveBlob method failed with the following exception:");
            console.log(ex);
        }

        if(!success)
        {
            // Get the blob url creator
            var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
            if(urlCreator)
            {
                // Try to use a download link
                var link = document.createElement('a');
                if('download' in link)
                {
                    // Try to simulate a click
                    try
                    {
                        // Prepare a blob URL
                        console.log("Trying download link method with simulated click ...");
                        var blob = new Blob([data], { type: contentType });
                        var url = urlCreator.createObjectURL(blob);
                        link.setAttribute('href', url);

                        // Set the download attribute (Supported in Chrome 14+ / Firefox 20+)
                        link.setAttribute("download", filename);

                        // Simulate clicking the download link
                        var event = document.createEvent('MouseEvents');
                        event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
                        link.dispatchEvent(event);
                        console.log("Download link method with simulated click succeeded");
                        success = true;

                    } catch(ex) {
                        console.log("Download link method with simulated click failed with the following exception:");
                        console.log(ex);
                    }
                }

                if(!success)
                {
                    // Fallback to window.location method
                    try
                    {
                        // Prepare a blob URL
                        // Use application/octet-stream when using window.location to force download
                        console.log("Trying download link method with window.location ...");
                        var blob = new Blob([data], { type: octetStreamMime });
                        var url = urlCreator.createObjectURL(blob);
                        window.location = url;
                        console.log("Download link method with window.location succeeded");
                        success = true;
                    } catch(ex) {
                        console.log("Download link method with window.location failed with the following exception:");
                        console.log(ex);
                    }
                }

            }
        }

        if(!success)
        {
            // Fallback to window.open method
            console.log("No methods worked for saving the arraybuffer, using last resort window.open");
            window.open(httpPath, '_blank', '');
        }
    })
    .error(function(data, status) {
        console.log("Request failed with status: " + status);

        // Optionally write the error out to scope
        $scope.errorDetails = "Request failed with status: " + status;
    });
};

Usage:

var downloadPath = "/files/instructions.pdf";
$scope.downloadFile(downloadPath);

Notes:

You should modify your WebApi method to return the following headers:

  • I have used the x-filename header to send the filename. This is a custom header for convenience, you could however extract the filename from the content-disposition header using regular expressions.

  • You should set the content-type mime header for your response too, so the browser knows the data format.

I hope this helps.

这篇关于使用AngularJS的ASP.NET Web API方法下载文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆