簡體   English   中英

從mvc web api httpresponse生成csv並通過angularjs接收它以供下載

[英]generate csv from mvc web api httpresponse and receive it by angularjs for download

我試圖從我的web api生成一個CSV文件,並通過angularjs接收該文件。 我有一個如下所示的API控制器:

 [HttpPost]
    public HttpResponseMessage GenerateCSV(FieldParameters fieldParams)
    {
        var output = new byte[] { };
        if (fieldParams!= null)
        {
            using (var stream = new MemoryStream())
            {
                this.Serialize(fieldParams, stream);
                stream.Flush();
                output = stream.ToArray();
            }
        }
        var result = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ByteArrayContent(output) };
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
        {
            FileName = "Fields.csv"
        };
        return result;
    }

在我的angularjs中,我有這個:

$scope.save = function () {
        var csvInput= extractDetails();

        // File is an angular resource. We call its save method here which
        // accesses the api above which should return the content of csv
        File.save(csvInput, function (content) {
            console.log(content);

            // only creates a csv file with "[object Object]" written in it
            var hiddenElement = document.createElement('a');
            hiddenElement.href = 'data:text/csv;charset=utf-8,\uFEFF' + encodeURI(content.Parameters);
            hiddenElement.target = '_blank';
            hiddenElement.download = 'myFile.csv';
            hiddenElement.click();
        });
    };

讓我們舉例來說,在我的API控制器中,響應的內容是

產量

{字節[152]}

[0]:83

[1]:101

[2]:44

[3]:67

[4]:10

當我在angularjs中收到這個並且我將content的值放在控制台日志(chrome)中時,這就是我得到的:

{Parameters:Array [1],$ promise:Object,$ resolved:true,$ get:function,$ save:function ...}

0: “S”

1:“e”

2:“,”

3:“C”

4:“↵”

$ promise:對象

$ resolved:true`

  1. 為什么angularjs中收到的content已包含字符而不是數組的字節?

  2. 如何以這樣的方式控制content :我只使用csv相關數據並刪除$promise$resolved 它們為什么首先包括在內? 如何刪除它們?

  3. 如果我正在做的事情是錯誤的,那么生成csv的正確方法是什么? :|

忘了更新這個,但我現在找到了解決這個問題的方法:

將有兩個API,一個(POST)將記住要在處理中使用的數據,另一個(GET)將分配文件。

POST:

    [HttpPost]
    public async Task<HttpResponseMessage> BuildFile(FileParameters fileParams)
    {
        var guid = Guid.NewGuid().ToString();
        if (fileParams!= null)
        {
            await Task.Run(() => FileContents.Add(guid, fileParams));
            return this.Request.CreateResponse(HttpStatusCode.OK, new { Value = guid });
        }
        return this.Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Invalid data");
    }

在AngularJs中,記住guid返回並將其傳遞給另一個api:

 location.href = '/api/file/generatefile' + '?guid=' + generatedGuidFromAPI + '&reportName=' + $scope.reportName;

這是MVC中的generatefile API控制器:

得到:

  [HttpGet]
    public async Task<HttpResponseMessage> GenerateFile(string guid, string reportName)
    {
        byte[] output = null;
        if (FileContents.ContainsKey(guid))
        {
            await Task.Run(() =>
            {
                using (var stream = new MemoryStream())
                {
                    this.CreateFile(FileContents[guid], stream);
                    stream.Flush();
                    output = stream.ToArray();
                }
            });
        }

        FileContents.Remove(guid);
        if (output != null)
        {
            var result = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ByteArrayContent(output) };
            result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
            result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
            {
                FileName = reportName + ".csv"
            };
            return result;
        }

        return this.Request.CreateErrorResponse(HttpStatusCode.NoContent, "No record found");
    }

使用location.href將導致瀏覽器自動下載文件,詢問是否保存。

我是這樣做的:(用鉻測試)

    // WebAPI controller action
    public IHttpActionResult Get(string rpt, DateTime date)
    {
        List<DailyMIReportViewModel> list = new List<DailyMIReportViewModel>();

        // Do some stuff to generate list of items

        // Download Requested
        if (rpt == "dailymidl")
        {
            // Create byte array of csv
            byte[] csvData = WriteCsvWithHeaderToMemory(list);
            // create FileContentResult of cdv byte array
            FileContentResult result = new FileContentResult(csvData, "application/octet-stream");
            // set filename in FileContentResult
            result.FileDownloadName = "Report.csv";

            return Ok(result);
        }
        // Data Requested
        return Ok(list);

        // Client-side angularjs
        // Called on button click
        $scope.generateMIDownload = function (forDate) {
            // Using $resource to return promise with FileContentResult payload
            reportsRepository.dailymidl(forDate).$promise.then(
            function (data) {
                //ok
                // NOTE: the base64 part is what got it working

                var dataUrl = 'data:application/octet-stream;base64,' + data.FileContents
                var link = document.createElement('a');
                angular.element(link)
                  .attr('href', dataUrl)
                  .attr('download', data.FileDownloadName)
                  .attr('target','_blank')
                link.click();
            },
            function (response) {
                //not ok
            });
        }

        // Reports Repository (for ref)
        angular.module('msgnr').factory('reportsRepository', function ($resource) {
            return {
                dailymidl: function (date) {
                    return $resource('/api/Report/', { rpt: 'dailymidl', date: date, toDate: date }).get();
            }
        }
    });

包括它可以幫助其他人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM