it-swarm.com.de

Laden Sie die Datei mithilfe von AngularJS von einer ASP.NET-Web-API-Methode herunter

In meinem Angular JS-Projekt habe ich ein <a> Anchor-Tag, das, wenn es angeklickt wird, eine HTTP GET-Anforderung an eine WebAPI-Methode sendet, die eine Datei zurückgibt. 

Jetzt möchte ich, dass die Datei an den Benutzer heruntergeladen wird, sobald die Anforderung erfolgreich ist. Wie mache ich das?

Das Anker-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) {
        // ...
    });
}

Meine WebAPI-Methode:

[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;
}
129
Amar Duplantier

Das Herunterladen von Binärdateien in ajax ist nicht großartig, es ist jedoch immer noch wird als Arbeitsentwurf entwickelt

Einfache Downloadmethode:

Sie können den Browser die angeforderte Datei einfach herunterladen, indem Sie den folgenden Code verwenden. Dies wird in allen Browsern unterstützt und löst natürlich die WebApi-Anfrage aus.

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

Ajax-Binärdownloadmethode:

Mit ajax können Sie die binäre Datei in einigen Browsern herunterladen. Im Folgenden finden Sie eine Implementierung, die in den neuesten Versionen von Chrome, Internet Explorer, FireFox und Safari funktioniert.

Es verwendet einen Antworttyp arraybuffer, der dann in eine JavaScript-Variable blob konvertiert wird, die entweder mit der saveBlob-Methode gespeichert wird (obwohl diese Option derzeit nur im Internet Explorer vorhanden ist) oder in eine Blob-Daten-URL umgewandelt wird, die von der geöffnet wird Browser, der den Download-Dialog auslöst, wenn der Mime-Typ für die Anzeige im Browser unterstützt wird.

Unterstützung für Internet Explorer 11 (behoben)

Hinweis: Internet Explorer 11 konnte die msSaveBlob-Funktion nicht verwenden, wenn diese mit einem Aliasing versehen wurde - möglicherweise eine Sicherheitsfunktion, aber wahrscheinlicher ein Fehler. Die Ermittlung der verfügbaren saveBlob-Unterstützung mit var saveBlob = navigator.msSaveBlob || navigator.webkitSaveBlob ... etc. verursachte eine Ausnahme. Deshalb testet der folgende Code nun separat auf navigator.msSaveBlob. Vielen Dank? 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;
    });
};

Verwendungszweck:

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

Anmerkungen:

Sie sollten Ihre WebApi-Methode so ändern, dass die folgenden Header zurückgegeben werden:

  • Ich habe den x-filename-Header verwendet, um den Dateinamen zu senden. Dies ist aus Gründen der Bequemlichkeit eine benutzerdefinierte Kopfzeile. Sie können jedoch den Dateinamen mithilfe von regulären Ausdrücken aus der content-disposition-Kopfzeile extrahieren.

  • Sie sollten den content-type-Mime-Header auch für Ihre Antwort festlegen, damit der Browser das Datenformat kennt.

Ich hoffe das hilft.

237
Scott

C # WebApi PDF downloadet alle, die mit Angular JS Authentication arbeiten

Web-API-Controller

[HttpGet]
    [Authorize]
    [Route("OpenFile/{QRFileId}")]
    public HttpResponseMessage OpenFile(int QRFileId)
    {
        QRFileRepository _repo = new QRFileRepository();
        var QRFile = _repo.GetQRFileById(QRFileId);
        if (QRFile == null)
            return new HttpResponseMessage(HttpStatusCode.BadRequest);
        string path = ConfigurationManager.AppSettings["QRFolder"] + + QRFile.QRId + @"\" + QRFile.FileName;
        if (!File.Exists(path))
            return new HttpResponseMessage(HttpStatusCode.BadRequest);

        HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
        //response.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
        Byte[] bytes = File.ReadAllBytes(path);
        //String file = Convert.ToBase64String(bytes);
        response.Content = new ByteArrayContent(bytes);
        response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
        response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
        response.Content.Headers.ContentDisposition.FileName = QRFile.FileName;

        return response;
    }

Angular JS Service

this.getPDF = function (apiUrl) {
            var headers = {};
            headers.Authorization = 'Bearer ' + sessionStorage.tokenKey;
            var deferred = $q.defer();
            $http.get(
                hostApiUrl + apiUrl,
                {
                    responseType: 'arraybuffer',
                    headers: headers
                })
            .success(function (result, status, headers) {
                deferred.resolve(result);;
            })
             .error(function (data, status) {
                 console.log("Request failed with status: " + status);
             });
            return deferred.promise;
        }

        this.getPDF2 = function (apiUrl) {
            var promise = $http({
                method: 'GET',
                url: hostApiUrl + apiUrl,
                headers: { 'Authorization': 'Bearer ' + sessionStorage.tokenKey },
                responseType: 'arraybuffer'
            });
            promise.success(function (data) {
                return data;
            }).error(function (data, status) {
                console.log("Request failed with status: " + status);
            });
            return promise;
        }

Entweder wird man tun

Angular JS Controller ruft den Dienst auf 

vm.open3 = function () {
        var downloadedData = crudService.getPDF('ClientQRDetails/openfile/29');
        downloadedData.then(function (result) {
            var file = new Blob([result], { type: 'application/pdf;base64' });
            var fileURL = window.URL.createObjectURL(file);
            var seconds = new Date().getTime() / 1000;
            var fileName = "cert" + parseInt(seconds) + ".pdf";
            var a = document.createElement("a");
            document.body.appendChild(a);
            a.style = "display: none";
            a.href = fileURL;
            a.download = fileName;
            a.click();
        });
    };

Und zuletzt die HTML-Seite

<a class="btn btn-primary" ng-click="vm.open3()">FILE Http with crud service (3 getPDF)</a>

Dies wird umgestaltet, indem nur der Code geteilt wird. Ich hoffe, es hilft jemandem, da ich eine Weile gebraucht habe, um das zu schaffen.

7
tfa

Für mich war das Web API Rails und clientseitig Angular mit Restangular und FileSaver.js

Web API

module Api
  module V1
    class DownloadsController < BaseController

      def show
        @download = Download.find(params[:id])
        send_data @download.blob_data
      end
    end
  end
end

HTML

 <a ng-click="download('foo')">download presentation</a>

Winkelsteuerung

 $scope.download = function(type) {
    return Download.get(type);
  };

Winkelservice

'use strict';

app.service('Download', function Download(Restangular) {

  this.get = function(id) {
    return Restangular.one('api/v1/downloads', id).withHttpConfig({responseType: 'arraybuffer'}).get().then(function(data){
      console.log(data)
      var blob = new Blob([data], {
        type: "application/pdf"
      });
      //saveAs provided by FileSaver.js
      saveAs(blob, id + '.pdf');
    })
  }
});
6
AnkitG

Wir mussten auch eine Lösung entwickeln, die sogar mit APIs arbeitet, die eine Authentifizierung erfordern (siehe diesen Artikel ).

Kurz gesagt, mit AngularJS haben wir es gemacht:

Schritt 1: Erstellen Sie eine dedizierte Direktive

// jQuery needed, uses Bootstrap classes, adjust the path of templateUrl
app.directive('pdfDownload', function() {
return {
    restrict: 'E',
    templateUrl: '/path/to/pdfDownload.tpl.html',
    scope: true,
    link: function(scope, element, attr) {
        var anchor = element.children()[0];

        // When the download starts, disable the link
        scope.$on('download-start', function() {
            $(anchor).attr('disabled', 'disabled');
        });

        // When the download finishes, attach the data to the link. Enable the link and change its appearance.
        scope.$on('downloaded', function(event, data) {
            $(anchor).attr({
                href: 'data:application/pdf;base64,' + data,
                download: attr.filename
            })
                .removeAttr('disabled')
                .text('Save')
                .removeClass('btn-primary')
                .addClass('btn-success');

            // Also overwrite the download pdf function to do nothing.
            scope.downloadPdf = function() {
            };
        });
    },
    controller: ['$scope', '$attrs', '$http', function($scope, $attrs, $http) {
        $scope.downloadPdf = function() {
            $scope.$emit('download-start');
            $http.get($attrs.url).then(function(response) {
                $scope.$emit('downloaded', response.data);
            });
        };
    }] 
});

Schritt 2: Erstellen Sie eine Vorlage

<a href="" class="btn btn-primary" ng-click="downloadPdf()">Download</a>

Schritt 3: Verwenden Sie es

<pdf-download url="/some/path/to/a.pdf" filename="my-awesome-pdf"></pdf-download>

Dadurch wird eine blaue Schaltfläche dargestellt. Wenn Sie darauf klicken, wird ein PDF heruntergeladen (Achtung: Das Backend muss PDF in Base64-Codierung!) Und in die Datei href eingefügt werden. Die Schaltfläche wird grün und wechselt zu Save. Der Benutzer kann erneut klicken und es wird ein Standarddialogfeld zum Herunterladen der Datei my-awesome.pdf angezeigt.

2
aix

Senden Sie Ihre Datei als Base64-String.

 var element = angular.element('<a/>');
                         element.attr({
                             href: 'data:attachment/csv;charset=utf-8,' + encodeURI(atob(response.payload)),
                             target: '_blank',
                             download: fname
                         })[0].click();

Wenn die attr-Methode nicht in Firefox funktioniert, können Sie auch die Java-Methode setAttribute verwenden

1
PPB

Ich habe eine Reihe von Lösungen durchlaufen, und ich habe festgestellt, dass dies für mich gut funktioniert hat.

In meinem Fall musste ich eine Post-Anfrage mit einigen Anmeldeinformationen senden .. _. Aber es hat sich gelohnt.

var printPDF = function () {
        //prevent double sending
        var sendz = {};
        sendz.action = "Print";
        sendz.url = "api/Print";
        jQuery('<form action="' + sendz.url + '" method="POST">' +
            '<input type="hidden" name="action" value="Print" />'+
            '<input type="hidden" name="userID" value="'+$scope.user.userID+'" />'+
            '<input type="hidden" name="ApiKey" value="' + $scope.user.ApiKey+'" />'+
            '</form>').appendTo('body').submit().remove();

    }
0
OneGhana

In Ihrer Komponente, z.

function getthefile (){
window.location.href='http://localhost:1036/CourseRegConfirm/getfile';
};
0
Shivani Jadhav

Sie können eine Showfile-Funktion implementieren, die Parameter der von WEBApi zurückgegebenen Daten und einen Dateinamen für die Datei, die Sie herunterladen möchten, übernimmt. Was ich getan habe war, einen separaten Browser-Dienst zu erstellen, identifiziert den Browser des Benutzers und übernimmt dann das Rendern der Datei basierend auf dem Browser. Wenn der Zielbrowser beispielsweise auf einem iPad verchromt ist, müssen Sie das FileReader-Objekt von javascripts verwenden.

FileService.showFile = function (data, fileName) {
    var blob = new Blob([data], { type: 'application/pdf' });

    if (BrowserService.isIE()) {
        window.navigator.msSaveOrOpenBlob(blob, fileName);
    }
    else if (BrowserService.isChromeIos()) {
        loadFileBlobFileReader(window, blob, fileName);
    }
    else if (BrowserService.isIOS() || BrowserService.isAndroid()) {
        var url = URL.createObjectURL(blob);
        window.location.href = url;
        window.document.title = fileName;
    } else {
        var url = URL.createObjectURL(blob);
        loadReportBrowser(url, window,fileName);
    }
}


function loadFileBrowser(url, window, fileName) {
    var iframe = window.document.createElement('iframe');
    iframe.src = url
    iframe.width = '100%';
    iframe.height = '100%';
    iframe.style.border = 'none';
    window.document.title = fileName;
    window.document.body.appendChild(iframe)
    window.document.body.style.margin = 0;
}

function loadFileBlobFileReader(window, blob,fileName) {
    var reader = new FileReader();
    reader.onload = function (e) {
        var bdata = btoa(reader.result);
        var datauri = 'data:application/pdf;base64,' + bdata;
        window.location.href = datauri;
        window.document.title = fileName;
    }
    reader.readAsBinaryString(blob);
}
0
Erkin Djindjiev