Я не уверен, что то, что я хочу делать, возможно.

В настоящее время я работаю над веб-приложением AngularJS, и мне нужно реализовать способ получения данных из моей базы данных, сохранения их в List<object>, синтаксического анализа этого List<object> в файле .csv и загрузки его в память, таким образом я могу отправить его обратно как HttpResponseMessage.

У меня уже есть все данные в переменной List<object>, и я буду использовать CSVHelper для синтаксического анализа их в файл, но все примеры, которые я нахожу в Интернете, показывают мне, как экспортировать файл локально с помощью File.WriteAllText(), и они все используют File.OpenRead(filePath) для чтения файла локально.

Как я могу создать и сохранить файл в памяти и отправить его обратно как HttpResponseMessage?


< Сильный > EDIT :

Покопавшись, я смог придумать это, хотя это не работает. Когда я запускаю код, я получаю сообщение «Этот сайт недоступен. Соединение прервано. ERR_CONNECTION_RESET» из Chrome.

Надеюсь, это поможет визуализировать то, что я пытаюсь сделать.

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);
        }
    }
0
Jacob Loncar 24 Окт 2018 в 00:49

2 ответа

Лучший ответ

Я смог найти ответ, собрав по кусочкам кое-что из того, что нашел в сети. Если кто-то столкнется с подобной проблемой, это код, который, как я обнаружил, работает в моем случае. 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);
        }
    }
0
Jacob Loncar 24 Окт 2018 в 22:24

Чтобы создать файл 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 в большой двоичный объект. Здесь есть множество примеров JS (Создание BLOB-объекта из base64 строка в JavaScript).

1
William 23 Окт 2018 в 23:02
52958314