发送我要制作的文件并将其作为IHttpActionResult存储在内存中

时间:2018-10-23 21:49:33

标签: c# http export-to-csv

我不确定我想要做什么。

我目前正在使用AngularJS网络应用程序,需要实现一种从数据库中获取数据,将其存储到List<object>,将List<object>解析为.csv文件并加载的方法在内存中,这样我就可以将其发送回HttpResponseMessage了。

我已经将所有数据保存在List<object>变量中,并且将使用CSVHelper将其解析为文件,但是我在网上找到的所有示例都向我展示了如何使用File.WriteAllText()在本地导出文件,他们都使用File.OpenRead(filePath)在本地读取文件。

如何创建文件并将其存储在内存中,并以HttpResponseMessage的形式发送回去?


编辑:

深入研究之后,我想出了这个办法,尽管它不起作用。当我运行代码时,我得到“无法访问此站点。连接已停止。 铬的ERR_CONNECTION_RESET”。

希望这有助于可视化我要执行的操作。

JavaScript

me.downloadFile = function (fileId) {

    $http({
        method: 'POST',
        url: 'api/notices/CheckFileExists',
        params: { fileId: fileId }
    }).then(function success(result) {
        if (result.data === 'Y') {
            me.downloadOpen("POST", 'api/notices/DownloadFile?fileId=' + fileId, "", "");
        }
        else {
            $mdToast.show(
                $mdToast.simple()
                    .textContent(result.data)
                    .position("bottom right")
                    .hideDelay(2000)
            );
        }
    });
};

me.downloadOpen = function (verb, url, data, target) {
    var form = document.createElement("form");
    form.action = url;
    form.method = verb;
    form.target = target || "_self";

    if (data) {
        for (var key in data) {
            var input = document.createElement("input");
            input.name = key;
            input.value = typeof data[key] === "object" ? JSON.stringify(data[key]) : data[key];
            form.appendChild(input);
        }
    }

    form.style.display = 'none';
    document.body.appendChild(form);
    form.submit();
    document.body.removeChild(form);

C#

[HttpPost]
    public HttpResponseMessage DownloadFile(int fileId)
    {
        var user = GetUser();
        var fileContent = NoticesMethods.GetNoticeFile(fileId, user);

        using (Globals.WebAppsImpersonator())
        {
            if (fileContent.Count > 0)
            {
                using (var mem = new MemoryStream())
                using (var writer = new StreamWriter(mem))
                using (var csvWriter = new CsvWriter(writer))
                {
                    csvWriter.Configuration.Delimiter = ",";
                    csvWriter.WriteField("File ID");
                    csvWriter.WriteField("Account");
                    csvWriter.WriteField("Move Date");

                    foreach (var row in fileContent)
                    {
                        csvWriter.WriteField("\"" + row.FileId + "\"");
                        csvWriter.WriteField("\"" + row.Account + "\"");
                        csvWriter.WriteField("\"" + row.MoveDate + "\"");
                    }

                    writer.Flush();

                    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
                    result.Content = new StreamContent(mem);
                    result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/csv");
                    result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
                    result.Content.Headers.ContentDisposition.FileName = "Notice.csv";

                    return result;
                }
            }
            return new HttpResponseMessage(HttpStatusCode.NotFound);
        }
    }

2 个答案:

答案 0 :(得分:1)

要创建一个csv文件并将其保存在内存中,您需要在CSVHelper代码之前实例化内存流。然后,您可以从控制器以base64字符串形式返回内存流字节数组。

[HttpGet]
public IHttpActionResult Get(params)
{
    var result = "";
    using (var memoryStream = new MemoryStream())
    {
        using (var streamWriter = new StreamWriter(memoryStream))
        using (var csvWriter = new CsvWriter(streamWriter))
        {
            csvWriter.WriteRecords(listOfObjects);
        } 

        result = Convert.ToBase64String(memoryStream.ToArray()); 
    }

    return Ok(result);
}

在前端,您可能需要利用FileSaver.js库。它要求您首先将base64字符串转换为Blob。这里有很多JS示例(Creating a Blob from a base64 string in JavaScript)。

答案 1 :(得分:0)

我可以通过将在网上找到的一些东西拼凑在一起来找到答案。如果有人遇到类似问题,这是我发现适用于我的情况的代码。 javascript是一样的,但是我对C#做了一些小的更改。

我发回StreamContent,而不是发回StringContent。这样,我要做的就是将数据写入CSV文件,然后将其读取为字符串。

这是代码:

[HttpPost]
    public HttpResponseMessage DownloadFile(int fileId)
    {
        var user = GetUser();
        var fileContent = NoticesMethods.GetNoticeFile(fileId, user);


        using (Globals.WebAppsImpersonator())
        {
            if (fileContent.Count > 0)
            {
                using (var mem = new MemoryStream())
                using (var reader = new StreamReader(mem))
                using (var writer = new StreamWriter(mem))
                using (var csvWriter = new CsvWriter(writer))
                {
                    csvWriter.Configuration.Delimiter = ",";
                    csvWriter.WriteField("File ID");
                    csvWriter.WriteField("Account");
                    csvWriter.WriteField("Move Date");
                    csvWriter.NextRecord();

                    foreach (var row in fileContent)
                    {
                        csvWriter.WriteField("\"" + row.FileId + "\"");
                        csvWriter.WriteField("\"" + row.Account + "\"");
                        csvWriter.WriteField("\"" + row.MoveDate + "\"");
                        csvWriter.NextRecord();
                    }

                    writer.Flush();
                    mem.Position = 0;

                    var file = reader.ReadToEnd();

                    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
                    result.Content = new StringContent(file);
                    result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/csv");
                    result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
                    result.Content.Headers.ContentDisposition.FileName = "Notice.csv";

                    return result;
                }
            }
            return new HttpResponseMessage(HttpStatusCode.NotFound);
        }
    }