Wyślij na serwer, odbierz PDF, dostarcz do użytkownika w / jQuery
Mam link, który użytkownik kliknie, aby uzyskać plik PDF. W jQuery tworzę Post ajax call to the server to get the PDF. PDF przychodzi do mnie z poprawnymi nagłówkami treści itp., które normalnie spowodowałyby otwarcie przeglądarki wtyczki Reader lub umożliwienie użytkownikowi zapisania pliku PDF.
Ponieważ otrzymuję plik PDF z wywołaniem ajax, nie jestem pewien, co zrobić z danymi, które otrzymuję w wywołaniu zwrotnym OnSuccess. W jaki sposób mogę przekazać dane, które otrzymuję do przeglądarki i zezwolić na jej domyślne wykonanie coś z odpowiedzią PDF?
7 answers
W ogóle nie potrzebujesz jQuery. Po prostu prześlij swój POST za pomocą formularza, a po stronie serwera dodaj nagłówek HTTP
Content-Disposition: attachment; filename="whatever.pdf"
Przeglądarka zrobi swoje domyślne działanie.
Alternatywnie, jeśli chcesz być bardziej ostrożny w zgłaszaniu błędów, które mogą wystąpić podczas generowania pliku PDF, możesz to zrobić. Opublikuj swoje parametry na serwerze za pomocą jQuery. Na serwerze Wygeneruj zawartość binarną i buforuj ją gdzieś przez kilka minut, dostępną za pomocą klucza, który umieścisz w sesji użytkownika i zwróci odpowiedź" sukces "Ajax na Twoją stronę(lub jeśli wystąpił błąd, zwróć odpowiedź "błąd"). Jeśli strona otrzyma odpowiedź na sukces, może natychmiast zrobić coś takiego:
window.location = "/get/my/pdf";
Serwer zwraca następnie buforowaną zawartość PDF. Pamiętaj, aby dołączyć nagłówek Content-Disposition, jak powyżej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-02 18:40:01
Spójrz na - wtyczka jQuery do pobierania plików w stylu Ajax
Całość plugin
to około 30 linijek kodu (łącznie z komentarzami).
Wywołanie jest dość podobne do wywołania jQuery ajax.
$.download('/export.php','filename=myPDF&format=pdf&content=' + pdfData );
Oczywiście, musisz ustawić nagłówki content-type I Content-Disposition po stronie serwera, tak jak w przypadku każdego takiego pobrania.
W Javie zrobiłbym coś takiego
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename="exported.pdf");
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-02 18:43:46
ODPOWIEDŹ wspominająca "jQuery Plugin do żądania pobierania plików Ajax-like" sprawiła, że skierowałem się w dobrym kierunku, ale nie zadziałało całkowicie w mojej sytuacji, ponieważ mam złożony obiekt i tablicę obiektów do przekazania jako moje kryteria wyszukiwania / DANE filtra. Pomyślałem, że podzielę się moim kodem na wypadek, gdyby ktoś inny wpadł w tę sytuację.
$.download = function (url, data, method) {
if (url && data) {
//convert the data object into input HTML fields
var inputs = '';
var convertToInput = function (key, keyStr, obj) {
if (typeof obj === 'undefined') {
return;
} else if (typeof obj === "object") {
for (var innerKey in obj) {
if (obj.hasOwnProperty(innerKey)) {
var innerKeyStr = '';
if (keyStr === '') {
innerKeyStr = innerKey.toString();
} else {
innerKeyStr = keyStr + "[" + innerKey.toString() + "]";
}
convertToInput(innerKey, innerKeyStr, obj[innerKey]);
}
}
return;
} else if ($.isArray(obj)) {
obj.forEach(function (item) {
convertToInput(key, keyStr + "[]", item);
});
return;
}
inputs += "<input type='hidden' name='" + keyStr + "' value='" + obj + "' />";
};
convertToInput(null, '', data);
//send request
jQuery('<form action="' + url + '" method="' + (method || 'post') + '">' + inputs + '</form>').appendTo('body').submit().remove();
};
};
$.download('/api/search?format=csv', searchData, 'POST');
To prawdopodobnie nie robi wielkiej różnicy, ale aby zapewnić jakiś kontekst, mam javascript i knockout UI wywołanie do WebAPI, MVC4 i nHibernate. Część "format=csv" łańcucha zapytania uruchamia MediaTypeFormatter, aby przekonwertować zwrócone modele na typ pliku CSV. Jeśli to zostawię, odzyskam modele z API i mogę wypełnić zgrabną siatkę do wyświetlania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-05 21:51:35
Miałem ten sam problem, ale na górze użyj RESTFUL webservice
do tego i mieć złożony obiekt danych, który muszę opublikować.
Moje rozwiązanie:
podobnie jak wtyczka jQuery buduję szablon temp i przesyłam go. Ale obiekt danych wysyłam jako parametr z zawartością json (używam tutaj AngularJS
ale powinien też działać z jQuery.param()
.)
Javascript:
$('<form target="_blank" action="' + appConstants.restbaseurl + '/print/pdf" method="POST">' +
"<input name='data' value='" + angular.toJson($scope.versicherung) + "' />" +
'</form>').appendTo('body').submit().remove();
Po stronie serwera używamy CXF REST Service
z JACKSON
Provider:
Spring Config:
<jaxrs:server id="masterdataService" address="/">
<jaxrs:serviceBeans>
<ref bean="printRestServiceBean" />
</jaxrs:serviceBeans>
<jaxrs:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />
<bean class="de.controller.ExceptionHandler" />
</jaxrs:providers>
</jaxrs:server>
W kontrolerze wyodrębniłem param i przekształcił go z powrotem do Pojo Javy:
package de.controller;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
@Path(Constants.PRINT_PATH)
@Consumes({ MediaType.APPLICATION_JSON, "application/x-www-form-urlencoded"})
@Produces("application/pdf; charset=UTF-8")
public class PrintRestController {
@Autowired
private PrintService printService;
@POST
@Produces("application/pdf")
@Path("/pdf")
public Response getPDF(@FormParam("data") String data) {
return printService.getPDF(json2Versicherung(data));
}
private Versicherung json2Versicherung(String data) {
Versicherung lVersicherung = null;
try {
ObjectMapper mapper = new ObjectMapper();
lVersicherung = mapper.readValue(data, Versicherung.class);
} catch(Exception e) {
LOGGER.error("PrintRestController.json2Versicherung() error", e);
}
return lVersicherung;
}
}
W PrintService buduję plik binarny pdf i odpowiedź:
@Override
public Response getPDF(Versicherung pVersicherung) {
byte[] result = ... //build the pdf from what ever
ResponseBuilder response = Response.ok((Object) result);
response.header("Content-Disposition", "inline; filename=mypdf.pdf");
return response.build();
}
To rozwiązanie działa na wszystkich przeglądarkach (nawet dla IE9, które nie mogą obsługiwać adresów URL danych) oraz na tabletach i smartfonach i nie ma problemów z popupblockerami
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-17 13:12:09
Wtyczka jQuery do żądania pobierania plików podobnych do Ajax to-zasadniczo-tworzenie formularza, dodawanie danych postu jako ukrytych pól, dodawanie ich do treści strony, przesyłanie i usuwanie.
W moim przypadku nie miałem formularza, tylko fragment danych do opublikowania w takim stanie, w jakim był. To spowodowało następujące rozwiązanie. Po stronie serwera mogę uzyskać dane po prostu odczytując parametr "data" z żądania i DEKODUJĄC go URI.
function postAndDownload(url, data) {
encodedData = encodeURIComponent(data);
$("<form>")
.attr("action", url)
.attr("method", "post")
.append(
$("input")
.attr("type", "hidden")
.attr("name", "data")
.attr("value", encodedData)
)
.appendTo("body")
.submit()
.remove();
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-04 07:20:59
Nie rozumiem, dlaczego chcesz żądanie ajax do pliku URL pobierania! Ale jeśli jest to bardziej jak klient sam generuje jakąś zawartość do pobrania-użyj Uri danych. Działa doskonale dla Chrome i Firefox 20+. Safari i IE nie! Jeśli Flash jest dozwolony, możesz użyć downloadifier.
Po przeczytaniu Twojego kodu widzę, że chcesz wysłać kilka parametrów. No chyba, że ciąg zapytania jest zbyt długi (IE8 - ma limit 2083) dlaczego po prostu nie użyć anchora z odpowiednim adresem url? $('a.export-csv').click( function (evt){
linkEl.attr('href','/export?' + encodeURIComponent(formQueryString()));
return true;
});
Powyższe umożliwia zmianę adresu URL przed wystąpieniem domyślnego zdarzenia (kliknięcia).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-08 03:18:59
Myślę, że najlepiej będzie utworzyć tymczasowy plik pdf w folderze Pobrane, a następnie załadować plik za pomocą pop-up z iframe.. chrome załaduje go natychmiast, ale przypuszczam, że dla innych wariantów Acrobat reader musi być zainstalowany, aby wyświetlić pdf, ale znowu możesz użyć FlashPaper zbyt:)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-25 10:04:56