2016-11-17 3 views
14

У меня есть ссылка на моей странице, по клику которой я пытаюсь создать PDF-документ, а затем отобразить приглашение «Открыть-Сохранить» в браузере.Быстрый файл скачать

Мой HTML (компонент реакции) имеет код ниже, где onclick вызывает функцию _getMyDocument, которая затем вызывает метод Webapi.

<div className="row"> 
    <a href="#" onClick={this._getMyDocument.bind(this)}>Test Link</a> 
</div> 

_getMyDocument(e) { 
      GetMyDocument(this.props.mydata).then(()=> { 
    }).catch(error=> { 

    }); 

Мой контроллер имеет код ниже

[HttpPost] 
[Route("Generate/Report")] 
public IHttpActionResult GetMyReport(MyData myData) 
{ 
    byte[] myDoc = MyBusinessObject.GenerateMyReport(myData); 
    var result = new HttpResponseMessage(HttpStatusCode.OK) 
     { 
      Content = new ByteArrayContent(myDoc) 
     }; 
     result.Content.Headers.ContentDisposition = 
      new ContentDispositionHeaderValue("attachment") 
      { 
       FileName = "MyDocument.pdf" 
      }; 
     result.Content.Headers.ContentType = 
      new MediaTypeHeaderValue("application/octet-stream"); 

     var response = ResponseMessage(result); 

     return response; 
    } 

В настоящее время весь код выполняется, но я не получаю файл PDF скачать приглашение. Что я здесь делаю неправильно?

объект Response на успех от lokks Ajax вызова, как показано ниже

enter image description here

+0

Пробовали ли вы мое решение. Пожалуйста, оставьте свой отзыв. – ScrapCode

+0

Я попытался назначить URL-адрес загрузки после ответа @Ermir Beqiraj. var file = new Blob ([response], {type: 'application/pdf'}); var fileURL = URL.createObjectURL (файл); window.location = fileURL; Это загрузка PDF, но недействительная. – San

+0

Что такое 'MyBusinessObject.GenerateMyReport (myData);' делать? .. он делает запрос в другое приложение? –

ответ

0

Ваш вопрос в том, что функция GetMyDocument получит файл PDF в качестве ответа сервера, и в настоящее время вы ничего не делаете с этим ответом , Вам нужно обработать ответ в обратном вызове. Сохранение файлов из javascript не совсем просто, поэтому я бы рекомендовал использовать внешнюю библиотеку, такую ​​как filesaver.js, чтобы помочь вам.

Это будет в конечном итоге выглядит как-то ...

_getMyDocument(e) { 
    GetMyDocument(this.props.mydata) 
    .then((response)=> { 
     const returnedFile = new Blob([response], { type: 'application/pdf'}); 
     saveAs(returnedFile); 
    }).catch(error=> { 

    }); 
+0

Пытаясь использовать Filesaver.js, как я могу прочитать данные из ответа ?. новый File() ожидает два аргумента и ожидает, что данные будут массивом. – San

+0

Посмотрел на это немного больше, и я думаю, нам нужно будет использовать blob, а не файл - я отредактировал. –

+0

var file = new Blob ([response], {type: 'application/pdf'}); FileSaver.saveAs (файл); Это создает пустой документ. Требуется ли какое-либо преобразование перед тем, как перейти к Blob? – San

0

В нашем приложении (угловой) мы должны были создать объект URL для этого с кодом, как:

WebAPI:

result = Request.CreateResponse(HttpStatusCode.OK); 
result.Content = new ByteArrayContent(data); 
result.Content.Headers.Add("Content-Type", "application/pdf"); 
result.Content.Headers.ContentDisposition = 
         new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") 
         { 
          FileName = "FileNameHere" 
         }; 

return result; 

JavaScript:

// HttpCall in here 
// On SuccessResponse 
    var file = new Blob([data], { 
        type: 'application/pdf' 
        }); 
    var fileURL = URL.createObjectURL(file); 
// create an anchor and click on it. 
    var ancorTag = document.createElement('a'); 
    ancorTag.href = fileURL;ancorTag.target = '_blank'; 
    ancorTag.download = 'CouponOrder.pdf'; 
    document.body.appendChild(ancorTag); 
    ancorTag.click(); 
    document.body.removeChild(ancorTag); 
+1

Это загружается файл, но отображается как поврежденный файл при попытке открыть. – San

+0

@San, откройте полученный файл в блокноте и посмотрите, не получаете ли вы контент, не являющийся PDF-документом, а именно сообщение об ошибке 500 или какое-либо исключение из вашего вызова на ' MyBusinessObject.GenerateMyReport' –

+0

Не исключено. Я вернул размер данных, возвращаемых MyBusinessObject.GenerateMyReport, и также написал его непосредственно в pdf-файл. – San

1

Простой способ сделать это - на вашем сервере использовать метод GET и получать данные по параметрам запроса.

Затем в клиентском приложении вы просто должны создать классическую ссылку:

<a href="http://your-server.com/your-resource?param1=123&param2=456">Test Link</a> 

Или использовать этот простой JS скрипт, если хотите, чтобы управлять им из вашей логики сценария:

window.open("http://your-server.com/your-resource?param1=123&param2=456"); 
6

Ваш Ответ от сервера выглядит хорошо. Недостающая часть заключается в том, что вы не обрабатываете этот ответ со стороны клиента правильно.

Предположим, что ваш ресурс url-объекта выглядит как внизу в js. (Т.е. вы уже знаете URL ресурса, если вы не знаете еще, то вам потребуется отдельный вызов на сервер, чтобы знать URL загрузки)

response.downloadUrl = app/media/fileId/document.pdf 

Все, что вам нужно сделать, это установить,

window.location = item.downloadUrl; 

Это приведет к тому, что браузер запросит ресурс с сервера, ответ от сервера должен включать Content-Disposition:attachment;. Это приведет к тому, что браузер отобразит диалоговое окно загрузки.

P.S. Недавно я работал над подобной функциональностью. Если у вас есть вопросы, пожалуйста, спросите.

Если вы хотите заставить браузер отображать приглашение загрузки для некоторого файла (ресурса), вы должны включить в ответ ответ (который вы уже сделали) Content-Disposition:attachment;.

+0

Я использую средство просмотра отчетов Microsoft для создания pdf-файла. чтобы установить URL-адрес загрузки. Я обновил свой вопрос, чтобы включить объект ответа. – San

+0

@San, путем загрузки URL-адреса Я имею в виду любой адрес веб-службы (запрос сервера), который w В ответ ответьте. Поэтому, если вызов в Microsoft viewer для отчетов возвращает вам pdf-файл, вам нужно назначить один и тот же запрос на вызов переменной 'window.location' – ScrapCode

+0

Я назначил URL-адрес, выполнив -> var file = new Blob ([response], {type: 'application/pdf'}); var fileURL = URL.createObjectURL (файл) – San

0

Создание контента предрасположенности и добавить его в заголовок ответа

var cd = new System.Net.Mime.ContentDisposition 
{ 
    // for example foo.bak 
    FileName = System.IO.Path.GetFileName(fileName), 
    // always prompt the user for downloading, set to true if you want 
    // the browser to try to show the file inline 
    Inline = false, 
}; 
Response.AppendHeader("Content-Disposition", cd.ToString());