FileDownload resolves into null - jsf

I have a filedownload that doesn't work as wanted. I followed the instructions provided in this thread, but the file that gets downloaded is just a file with the name null but of the size of the file i wanted to download originally. The command i use is
<p:commandLink ajax="false">
Download
<p:fileDownload value="#{dtEditView.file}"/>
</p:commandLink>
My bean consists of the following
public StreamedContent getFile() throws IOException {
path = "C:\\test.jpeg";
contentType = FacesContext.getCurrentInstance().getExternalContext().getMimeType(path);
return new DefaultStreamedContent(new FileInputStream(path), contentType);
}
What am i doing wrong and what am i missing? I am using Primefaces 5.2.
Edit: I renamed the file into the file extension it is supposed to be and it appears to be what i wanted. The remaining questions are still?
Why is it renamed to null?
How can i set the correct file extension in an automatical manner?

Just add the filename you want to use for download to the constructor of DefaultStreamedContent:
return new DefaultStreamedContent(new FileInputStream(path), contentType, "filename.jpeg");
or to keep the same name as the resource:
return new DefaultStreamedContent(new FileInputStream(path), contentType, path.getFileName().toString());
compare with the bean in the showcase:
http://www.primefaces.org/showcase/ui/file/download.xhtml

Related

How to rename PDF in primefaces media tag

I am using streamedcontent in primefaces and using media tag to show it. When download button is pressed in the viewer it downloads file with the name dynamiccontent.properties. Is there any way to rename it?
I am using html4, java 7 and primefaces 5.2.24.
I have tried to set parameter #toolbar to hide the toolbar like below but it is not working:
<p:media id="pdfViewer" value="#{mybean.pdfMedia}" width="100%" height="90%" player="pdf" cache="false" >
<f:param name="#toolbar" value="0"></f:param>
</p:media>
and my streamed content is generating from iText like this:
baos = new ByteArrayOutputStream();
document = new Document();
document.setPageSize(PageSize.A4);
document.setMargins(70, 70, 100, 100);
writer = PdfWriter.getInstance(document, baos);
document.open();
document.newPage();
XMLWorkerHelper.getInstance().parseXHtml(writer, document,
new ByteArrayInputStream(pageContents));
document.close();
InputStream stream = new ByteArrayInputStream(baos.toByteArray());
StreamedContent pdfMedia = new DefaultStreamedContent(stream, "application/pdf");
Is there any way to rename the it? or is there any way to hide the tool bar?
This was a bug in PF 5.2.24 that you are using and is fixed in PF 6.1 or higher.
See this bug ticket: https://github.com/primefaces/primefaces/issues/2055
Make sure to set "NAME" in the DefaultStreamedContent by either using the constructor org.primefaces.model.DefaultStreamedContent.DefaultStreamedContent(InputStream stream, String contentType, String name) or the org.primefaces.model.DefaultStreamedContent.setName(String) method.
You need to set a Name for your streamed content by either using the constructor
org.primefaces.model.DefaultStreamedContent.DefaultStreamedContent(InputStream stream, String contentType, String name) or the org.primefaces.model.DefaultStreamedContent.setName(String) method.

Unable to display pdf in an iframe JSF [duplicate]

This question already has an answer here:
How to include file from external local disk file system folder in JSF
(1 answer)
Closed 6 years ago.
I am letting the user upload a file and am storing it as so
List<Meetingsattachment> mal= new ArrayList<Meetingsattachment>();
meeting.setMeetingsattachments(mal);
Random rand=new Random();
int num=Math.abs(rand.nextInt());
String dirname="/path/to/files/"+meeting.getDescription()+"-"+num;
File dir= new File(dirname);
System.out.println(dir.getAbsolutePath());
if(! dir.exists())
dir.mkdir();
for(UploadedFile uf:ufl){
Meetingsattachment ma=new Meetingsattachment();
ma.setAttachment(dirname+"/"+uf.getFileName());
File file = new File(dirname+"/"+uf.getFileName());
try (FileOutputStream fop = new FileOutputStream(file)) {
// if file doesn't exists, then create it
if (!file.exists()) {
file.createNewFile();
}
// get the content in bytes
fop.write(IOUtils.toByteArray(uf.getInputstream()));
fop.flush();
fop.close();
meeting.addMeetingsattachment(ma);
System.out.println("Done");
} catch (IOException e) {
e.printStackTrace();
}
}
int meetingid=mrm.addMeeting(meeting);
return "meetings?faces-redirect=true";
What I am basically doing is taking the file storing it at /path/to/files/ and then storing the location in my database, so value in db is as so
/path/to/files/t2-672409104/1.pdf
I am able to download the file as so
Meetingsattachment ma=(Meetingsattachment) actionEvent.getComponent().getAttributes().get("attachment");
//System.out.println("here "+form.getRqid());
try{
InputStream stream = new FileInputStream(new File(ma.getAttachment()));
String fl=ma.getAttachment();
System.out.println(fl);
String filename=fl.split("/")[5];
//System.out.println(ra.getRaid());
setFile(new DefaultStreamedContent(stream,"application/pdf",filename));
in the jsf
<ui:repeat var="meetattachment" value="#{meet.meetingsattachments}">
<h:outputText value="#{meetattachment.attachment}" />
<p:commandButton icon="ui-icon-arrowthickstop-1-s"
onclick="PrimeFaces.monitorDownload(showStatus, hideStatus)"
actionListener="#{meetBean.buttonAction}">
<f:attribute name="attachment" value="#{meetattachment}"></f:attribute>
<p:fileDownload value="#{meetBean.file}" />
</p:commandButton>
But when I try to display the file in an iframe I just get an iframe showing resource not found
<ui:repeat var="meetattachment" value="#{meet.meetingsattachments}">
<h:outputText value="#{meetattachment.attachment}" />
<p:lightBox iframe="true">
<h:outputLink value="#{meetattachment.getAttachment()}">
preview2
</h:outputLink>
</p:lightBox>
<br />
</ui:repeat>
The value that the h:outputlink is getting is /path/to/files/t2-672409104/1.pdf
In the developer webconsole I can see the following error
GET
http://localhost:8080/path/to/files/t2-672409104/1.pdf not found
so I think the problem is the path it is trying to use to find the file, from my understanding if I store the file using the relative path /path/to/files the actual path for the file is C:\path\to\files
I tried hardcoding the value as such just to test
<h:outputLink value="C:\path\to\files\t2-672409104\1.pdf">
I get a message saying it cannot understand the protocol C
So my question basically is how do I provide the path to these files to open them in a frame
The way jsf work out the links is different. That is the reason you get the file not found error. If you want to open the file inside an iframe then you need to do some extra works. There is pdfjs library which you can download and use it to show the pdf inside an iframe. In primefaces there is a component to do that. You can use the primefaces source to see how the same is accomplished. If you want more info or complete hand holding please do let me know.

Show error and change doneLabel of rich:fileUpload in upload listener method

I have to upload CSV file and I have to validate some values of file, for example does not allow negative value. Then, I need validate it and that file does not apear like "done" or "uploaded". I need handle an error on display it.
<rich:fileUpload
fileUploadListener="#{configClientBean.listener}"
ontyperejected="alert('some error');"
maxFilesQuantity="1"
onuploadcomplete="#{rich:component('waitPanelInterno')}.hide();"
onfilesubmit="#{rich:component('waitPanelInterno')}.show();"
render="pnlMensajes, idTableClients, scrollRegistros, outputPanelDetalle"
autoclear="true">
<rich:message for="uploadConfigClient" />
<a4j:ajax event="uploadcomplete" execute="popupFileLoad"
render="panelCarga, pnlMensajes" />
</rich:fileUpload>
In the Backing bean I can validate some things, but I cant show errors or change the behavior of "rich:fileUpload" compoment for example doneLable can not be displayed.
public void listener(FileUploadEvent event) throws Exception {
try {
UploadedFile file = event.getUploadedFile();
ByteArrayInputStream bais = new ByteArrayInputStream(file.getData());
InputStreamReader is = new InputStreamReader(bais, getMessage("iso"));
BufferedReader bufRead = new BufferedReader(is);
while ((registro = bufRead.readLine()) != null) {
if(cvsLine[1].isEmpty()){
// stop process
// Throw error
}
}
}
Thanks for your time.
To add extra behavior to the rich:fileUpload component that is not default is by creating your own file upload component (ex. myown:fileUpload) based on the rich:fileUpload source code and the use of the Component Development Kit.
A second solution could be by adding one extra message field that is described in this post: RichFaces fileupload and h:message problem

UploadedFile is null when uploading file with <p:fileUpload mode="simple">

I need to upload an image into the server.
I'm using primefaces, here is my code:
deposit.xhtml
<h:form>
<p:fileUpload mode="simple"
allowTypes="/(\.|\/)(gif|jpe?g|png)$/"
value="#{imageHandler.uploadedPicture}" />
<p:commandButton action="#{imageHandler.savefile(imageHandler.uploadedPicture)}"
value="Déposer" ajax="false" />
</h:form>
ImageHandler:
#ManagedBean (name = "imageHandler")
#RequestScoped
public class ImageHandler {
private UploadedFile uploadedPicture; // +getter+setter
public void savefile(UploadedFile uploadedPicture)
{
try {
InputStream input = uploadedPicture.getInputstream();
File folder = new File("C:\\Users\\Clyde\\Documents\\NetBeansProjects\\DSJEE\\web\\resources\\Items");
String filename = FilenameUtils.getBaseName(uploadedPicture.getFileName());
String extension = FilenameUtils.getExtension(uploadedPicture.getFileName());
File file = File.createTempFile(filename + "-", "." + extension, folder);
Files.copy(input, file.toPath());
FacesContext.getCurrentInstance().getExternalContext().redirect("index2.xhtml");
} catch (IOException ex) {
Logger.getLogger(ImageHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Concerning the trace here is the error I get, those are 3 lines that I have picked from the trace:
javax.faces.el.EvaluationException: java.lang.NullPointerException
Caused by: java.lang.NullPointerException
at ImageHandler.savefile(ImageHandler.java:43)
In other words, it's coming from here:
InputStream input = uploadedPicture.getInputstream();
I have tried many things to get rid of that error. I used savefile() without parameters, changed the scope, etc... Still can't go on. How is this caused and how can I solve it?
It will be null in the action method when the browser is unable to send the file contents along with the request body, or when the server is unable to grab the file contents from the request body.
In order to let the broswer send the file contents (and thus not only the name), you need to make sure that the request body encoding type is set to multipart/form-data. This is to be achieved by setting the enctype attribute of the form as below:
<h:form enctype="multipart/form-data">
Unrelated to the concrete problem, the below doesn't make sense:
<p:commandButton action="#{imageHandler.savefile(imageHandler.uploadedPicture)}">
You don't need to pass a bean property forth and back to the very same bean. Just let the action method access it directly.
<p:commandButton action="#{imageHandler.savefile}">
Also, the attempt to save the uploaded file in IDE project folder is a bad idea. Don't do that. Store it elsewhere. See also a.o. Uploaded image only available after refreshing the page.

uploading two files with JSF results in two times the same file

I have a JSF page + Bean to upload a file and preview the result (it's for images). In the bean the upload method puts the data (base64) in a list and the JSF page loops through the list to display the images.
So far it works as expected for the first image. But when I upload a second image there are two things that might go wrong:
the first image gets uploaded again instead
Or, with a little change in the code the second image does not get uploaded at all until I reselect the file again and upload it.
JSF page
<h:form enctype="multipart/form-data" id="uploadForm" prependId="false">
<!-- here I loop through the list to preview the images -->
<c:forEach var="image" items="#{bean.imageList}">
<h:graphicImage value="#{image}" />
</c:forEach>
<!-- that's the upload -->
<h:inputFile id="file" value="#{bean.uploadedFile}" />
<h:commandButton value="submit" action="#{bean.uploadFile}" />
</h:form>
bean
private Part uploadedFile; // the Part with the uploaded file
private ArrayList<String> imageList; // the list of images (base64 encoded)
public void uploadFile() throws IOException{
if(null != uploadedFile){
String imageType = "data:" + uploadedFile.getContentType() + ";base64,"; // will be something like: "data:image/png;base64,"
InputStream inputStream = uploadedFile.getInputStream(); // getting the inputStream from the Part
byte[] imageData; // array to but the image data
try(BufferedInputStream bis = new BufferedInputStream(inputStream)){ // converting the inputStream to a buffered one
imageData = new byte[bis.available()]; // initializing the byte array with the right size
bis.read(imageData); // reading / writing the image data
// HERE: if I comment out the next line, the second upload will upload the first image again.
// but if I set the Part to null, the second upload will result in nothing (page reloads, no data uploaded) and I have to upload it again
uploadedFile = null;
}
imageList.add(imageType + javax.xml.bind.DatatypeConverter.printBase64Binary(imageData)); // this adds the base64 image string to the list of images
}
}
My bean is #ViewScoped (I need it to be that way for other things).
So my guess was that the Part uploadedFile just didn't get the new image data for the second file, but as I said, when setting it to null it just skips the second upload process.
Does anyone see what I am doing wrong?
You might try the following.
byte[] imageData = new byte[uploadedFile.getSize()];
try (BufferedInputStream bis = new BufferedInputStream(inputStream)) {
bis.read(imageData);
uploadedFile.delete();
}
Using Part.getSize()
Not relying on available() which makes no guarantee that all is available
Using delete() to clear the bean
(Not tried it myself.)

Resources