Как использовать JQuery для загрузки файла или использовать Ajax для отображения страницы с ошибкой - PullRequest
0 голосов
/ 17 декабря 2018

Я работаю над одностраничным приложением, использующим ASP.Net Core MVC и JQuery (выполнение полного обновления страницы сбрасывает некоторые длительные процессы, поэтому я должен использовать AJAX для всей навигации, чтобы избежать этого.)

Я хочу разрешить пользователю загружать PDF, который может быть достаточно просто обработан с помощью моего PdfController:

public async Task<IActionResult> GetFile(int FileID)
{
    byte[] fileBytes = await _myService.GetFile(FileID);
    return File(fileBytes, "DesiredMimeType", "DesiredFileName");
}

В этом простом случае я могу использовать что-то вроде <a href="/Pdf/GetFile?FileID=123">Get File 123</a> и загрузка файловничего не напортачив.Проблема в том, что иногда мой сервис выдает исключение, если параметры неверны.Я хотел бы иметь возможность отображать пользовательскую страницу ошибки (используя AJAX), поэтому теперь мое действие контроллера становится:

public async Task<IActionResult> Index(int FileID)
{
    try
    {
        byte[] fileBytes = await _myService.GetFile(FileID);
        return File(fileBytes, "DesiredMimeType", "DesiredFileName");
    }
    catch (MyCustomException ex)
    {
        return PartialView("MyErrorPage", new MyErrorViewModel(ex));
    }
}

Это прекрасно работает на стороне сервера, но я не знаю, как справитьсяэто на стороне клиента.JavaScript должен выглядеть примерно так:

function getFile(fileID) {
    $.get('/Pdf/GetFile?FileID=' + fileID, function (data) {
        // pseudo code - not sure what to do here
        if (isFile(data)) {
            // then prompt a download and leave the DOM alone
        } else {
            // display error page
            $('#ajax-container').html(data);
        }
    }).fail(function (jqXHR, textStatus, errorThrown) {
        notify('Web service responded with ' + textStatus);
    });
}

Итак, мой вопрос: как я могу использовать JQuery или JavaScript, чтобы определить, является ли data файлом или частичным представлением, и как я могу вызватьскачать файл, если это файл?Если есть лучший подход, я также открыт для рекомендаций.

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Благодарность идет к Капитану Реду за то, что он дал мне ответ.Вот полное решение для тех, у кого такая же проблема.В PdfController.cs:

public async Task<IActionResult> Generate(string Foo, int Bar)
{
    try
    {
        // TODO: Include a randomized directory in the path so that a malicious user is less likely to guess a file path
        // TODO: Set appropriate permissions on the root pdf folder for IIS App Pool User (if using IIS)
        string relativePath = await _myService.CreateTempFile(Foo, Bar);
        return Json(new { redirect = Url.Action("Download", new { FilePath = relativePath }) });
    }
    catch (MyCustomException ex)
    {
        return PartialView("MyErrorPage", new MyErrorViewModel(ex, Foo, Bar));
    }
}

public async Task<IActionResult> Download(string FilePath)
{
    string tempFilePath = System.IO.Path.Combine(_hostingEnvironment.WebRootPath, "myPdfDir", FilePath);
    byte[] fileBytes = await System.IO.File.ReadAllBytesAsync(tempFilePath);

    // clean up the temp file
    System.IO.File.Delete(tempFilePath);
    Directory.Delete(Path.GetDirectoryName(tempFilePath));

    return File(fileBytes, "MyMimeType", "MyFileName");
}

В JavaSript:

function getPDF(foo, bar) {
    $.get('/Pdf/Generate?Foo=' + foo + '&Bar=' + bar, function (data) {
        if (data.redirect) {
            // we got a url for the pdf file
            window.location.replace(data.redirect); // downloads without affecting DOM
        } else {
            // we got a PartialView with the error page markup
            $('#ajax-container').html(data);
        }
    }).fail(function (jqXHR, textStatus, errorThrown) {
        // error handling
    });
}
0 голосов
/ 17 декабря 2018

Вы можете попытаться вернуть дополнительный флаг вместе с вашим ответом.

    public async Task<IActionResult> Index(int FileID)
    {
        try
        {
            string filePath = await _myService.GetFilePath(FileID);
            return  Json (new { status = "valid" , file = Url.Action("Download", new {FilePath = filepath})});
        }
        catch (MyCustomException ex)
        {
            return Json(new { status = "Invalid", pv = PartialView("MyErrorPage", new MyErrorViewModel(ex)) });
        }
    }
    
    public async Task<IActionResult> Download(string FilePath )
    {
       string tempFilePath = System.IO.Path.Combine(_hostingEnvironment.WebRootPath, "FILE-DIR", FilePath);
       byte[] fileBytes = await System.IO.File.ReadAllBytesAsync(tempFilePath);
      
     //Clean up the temp file 

       return file = File(fileBytes, "MIME-TYPE", "FILE-NAME");
    }

Тогда ваш код js будет:

        // pseudo code - not sure what to do here
        if (data.status == "valid")) {
            // then prompt a download and leave the DOM alone
            window.location.replace(data.file);
        } else {
            // display error page
            $('#ajax-container').html(data.pv);
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...