Incapable d'afficher le PDF dans le p:médias générés à partir du contenu diffusé en continu dans Primefaces
J'essaie de montrer inline PDF qui est ouvert dans une nouvelle fenêtre de navigateur. J'ai scénario suivant:
- Dans certains ActionListen qui est appelée par ajax je génère des PDF de contenu, de mettre les données dans la session, et l'envoyer Javascript à exécuter (
window.open
pour ouvrir une nouvelle page pour afficher PDF) - Sur la page ouverte, j'ai juste
p:media
balise à l'intérieur deh:body
avec la valeur pointant versStreamedContent
:
Maintenant, sur cette page de mon PDF n'est pas généré. Dans le journal, je peux le voir, ces deux lignes:
org.primefaces.application.PrimeResourceHandler handleResourceRequest
SEVERE: Error in streaming dynamic resource. Expression cannot be null
J'ai commencé à déboguer et de trouver un certain nombre de choses.
Tout d'abord, j'ai ajouté un point d'arrêt à @PostConstruct
méthode de mon RequestScoped
bean. Ce qui est intéressant, c'est que le point d'arrêt est atteint deux fois, et à ma grande surprise, après que le format PDF est montré parfaitement?!
Après un peu de débogage à travers PrimeResourceHandler
je comprendre que, dans certains cas ValueExpression
n'est pas calculé, en fait, il jette NullPointerException
, et de nouveau pendant le débogage, j'ai vu que les deux demandes sont envoyées, et la deuxième requête échoue, car dynamicContentId
est supprimé dans la première demande, et le deuxième appel à handleResourceRequest
n'a pas de sens.
Grâce à Firebug je vois deux demandes, la première qui est bon avec les données PDF, et la deuxième qui est bien aussi avec le type de contenu application/pdf mais vide, avec une taille de 0.
page xhtml:
<html>
<h:head></h:head>
<h:body>
<p:media value="#{reportBean.streamedContent}" player="pdf" width="500" height="500"/>
</h:body>
</html>
backing bean:
@RequestScoped
public class StampaListeBackingBean implements Serializable {
private static final long serialVersionUID = 1L;
private StreamedContent streamedContent;
@PostConstruct
public void init() {
Map<String, Object> session = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
byte[] b = (byte[]) session.get("reportBytes");
if (b != null) {
streamedContent = new DefaultStreamedContent(new ByteArrayInputStream(b), "application/pdf");
}
}
public StreamedContent getStreamedContent() {
if (FacesContext.getCurrentInstance().getRenderResponse()) {
return new DefaultStreamedContent();
} else {
return streamedContent;
}
}
public void setStreamedContent(StreamedContent streamedContent) {
this.streamedContent = streamedContent;
}
}
J'ai besoin de comprendre pourquoi les deux demandes sont envoyées à la page avec p:media
tag, et à comprendre comment faire ce travail. Backing bean est la portée de la requête, il crée StreamedContent
dans @PostConstruct
méthode, et a getter et setter pour ce champ. Primefaces version 3.4.2, Mojarra 2.1.14.
AJOUTÉ:
Il est facile de reproduire mon problème. Si le code de init
méthode est remplacé par le suivant:
FileInputStream fis = new FileInputStream(new File("C:\\samplexxx.pdf"));
streamedContent = new DefaultStreamedContent(fis, "application/pdf");
problème peut être reproduit.
<p:graphicImage>
et répondu en détail, entre autres ici: stackoverflow.com/questions/8207325/... Comme l'a observé exception, désolé, aucune idée. Quelques cas concrets de code serait utile.J'ai ajouté le xhtml et le code java, il est très simple. J'ai aussi ajouté mon inspection de Firebug.
Si vous utilisez un chemin d'accès statique comme
<p:media value="some.pdf">
? Juste pour exclure des ressources servlet d'en être la cause. Et que diriez-PrimeFaces propre vitrine exemple? Cela fonctionne pour vous aussi? Juste pour exclure navigateur d'être la cause (il fonctionne pour moi) primefaces.org/showcase-labs/ui/media.jsfIl fonctionne parfaitement. Primefaces exemples fonctionne aussi très bien. Mais comme je peux voir, ils utilisent également les chemins d'accès statiques dans tous les exemples. J'ai également expérimenté avec différentes étendues de haricot, mais il n'a pas aidé.
OriginalL'auteur partlov | 2013-01-23
Vous devez vous connecter pour publier un commentaire.
Je peux reproduire votre problème. En effet, elle ne fonctionne pas dans Firefox (ni dans IE9, mais il fonctionne dans Chrome). PrimeFaces plomb Cagatay a également mentionné que plusieurs fois.
Je ne suis pas sûr si c'est un bug dans le PrimeFaces gestionnaire de ressources ou dans le navigateur. Je vais le laisser dans le milieu.
En attendant, votre meilleur pari est un simple web servlet pour le travail. Il suffit de créer cette classe:
Et à l'appeler comme suit:
Que c'est. Pas de configuration XML nécessaire. Il fonctionne pour moi dans tous les navigateurs. Selon les conditions de fonctionnement, vous pouvez régler plus finement en-têtes de réponse liés à la mise en cache du navigateur.
Vous êtes les bienvenus.
Je pense que le vrai problème est
PrimeResourceHandler.handleResourceRequest
, en partie enfin est cette lignesession.remove(dynamicContentId)
. C'est peut-être un point où ces deux demandes ont condition de course.Avec la servlet solution de contournement, Firefox envoie 1 seule demande sur le fichier PDF au lieu de 2. Donc, le problème est en fait dans la réponse de la 1ère demande; le navigateur en quelque sorte ne pouvait pas traiter avec elle. Si j'ai plus de temps je ferais une enquête, mais pas maintenant 🙂
Merci BalusC. -Bien, c'est triste qu'en 2015, nous devons recourir à la "solution de contournement" pour IE11. (IE11 était encore en train de les "doivent commencer par" %PDF-' erreur, donc je suis en utilisant votre servlet technique)
OriginalL'auteur BalusC
Il n'est pas un navigateur ou primefaces problème, juste une drôle de problème de lecture.
De la lecture est appelée deux fois par p:les médias (ou si vous actualisez la page que plusieurs fois), mais seulement le 1er appel reçoit les données correctes. StreamedContent encapsule un InputStream, qui a la propriété qu'il ne donnera aucun octets si le flux est à la fin du fichier. La première fois qu'il est lu à sa fin (données est ok), mais chaque appel suivant aurez pas de données. 🙂
javadoc de inputStream.lire():
Si aucun octet est disponible, car le flux est à la fin du fichier, la valeur -1 est renvoyée; sinon, au moins un octet est lu et stocké dans b.
Solution:
OriginalL'auteur steve