WARNING - OUTDATED CONTENT!
This article is targeted on JSF 1.2.
For JSF 2.0/2.1 with Tomahawk, please checkout my answer on this Stack Overflow question.
For JSF 2.0/2.1 on Servlet 3.0 with a custom component, please checkout this article.
For JSF 2.2, just use its native file upload component in flavor of
<h:inputFile>
whose value can be tied to ajavax.servlet.http.Part
property, see also my answer on this Stack Overflow question.
Upload and store files
Downloading files is made relatively easy using a FileServlet, but uploading files is a bit harder. Entering/selecting the raw absolute file path in h:inputText and sending it to the server so that it can be used in a File object isn't going to work, as the server doesn't have access to the client's file system. That will work only if the server as well as the client runs on the same machine and that wouldn't occur in real life.
To browse and select a file for upload you basically need a HTML input type="file" field in the form. As stated in the HTML specification you have to use the POST method and the enctype attribute of the form have to be set to "multipart/form-data". Unfortunately the Sun JSF Reference Implementation Mojarra doesn't provide a component out of the box which renders a input type="file" field. But the MyFaces Tomahawk component library, which can also be integrated in Sun JSF Reference Implementation Mojarra, provides us the t:inputFileUpload component.
Back to top
Integrating Tomahawk in Mojarra
Assuming that you already have a Mojarra environment, you just need to add at least the following JAR's to the classpath, e.g. /WEB-INF/lib. The version numbers doesn't matter that much, as long as you get the newest.
- tomahawk-1.1.6.jar
- commons-fileupload-1.2.jar
- commons-io-1.4.jar
- commons-logging-1.1.1.jar
- commons-el.jar
The Tomahawk JAR is the Tomahawk component library itself which under each contains the t:inputFileUpload component and the ExtensionsFilter. The commons-fileupload and commons-io JAR's are required for the file upload. They contains a multipart/form-data parser and several I/O utilities respectively. The commons-logging and commons-el JAR's are required by the core of the Tomahawk component library.
After adding the JAR's, open your web.xml and add the ExtensionsFilter to it. It should filter multipart/form-data requests and make use of the commons-fileupload to parse the request. To get uploading files work in JSF, it should at least be mapped on the servlet name of the FacesServlet, which may differ per environment. By default it is "Faces Servlet". Just check the servlet name in its <servlet> definition.
<filter> <filter-name>Extensions Filter</filter-name> <filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class> </filter> <filter-mapping> <filter-name>Extensions Filter</filter-name> <servlet-name>Faces Servlet</servlet-name> </filter-mapping>
It is not required, but you can configure the ExtensionsFilter with one or more of the following useful init-param settings which you can put in the <filter> tag:
<init-param> <description> Set the size limit for uploaded files. Format: 10 - 10 bytes 10k - 10 KB 10m - 10 MB 1g - 1 GB </description> <param-name>uploadMaxFileSize</param-name> <param-value>100m</param-value> </init-param> <init-param> <description> Set the threshold size - files below this limit are stored in memory, files above this limit are stored on disk. Format: 10 - 10 bytes 10k - 10 KB 10m - 10 MB 1g - 1 GB </description> <param-name>uploadThresholdSize</param-name> <param-value>100k</param-value> </init-param> <init-param> <description> Set the path where the intermediary files will be stored. </description> <param-name>uploadRepositoryPath</param-name> <param-value>/temp</param-value> </init-param>
Back to top
Basic use example
Here is a basic use example of a JSF file and the appropriate backing bean which demonstrates the working of the t:inputFileUpload.
taglib uri="http://java.sun.com/jsf/core" prefix="f" taglib uri="http://java.sun.com/jsf/html" prefix="h" taglib uri="http://myfaces.apache.org/tomahawk" prefix="t" <!DOCTYPE html> <f:view> <html lang="en"> <head> <title>File upload test</title> </head> <body> <h:form id="uploadForm" enctype="multipart/form-data"> <h:panelGrid columns="3"> <h:outputLabel for="file" value="Select file" /> <t:inputFileUpload id="file" value="#{myBean.uploadedFile}" required="true" /> <h:message for="file" style="color: red;" /> <h:panelGroup /> <h:commandButton value="Submit" action="#{myBean.submit}" /> <h:message for="uploadForm" infoStyle="color: green;" errorStyle="color: red;" /> </h:panelGrid> </h:form> <h:outputLink value="file/#{myBean.fileName}" rendered="#{myBean.fileName != null}"> Download back </h:outputLink> </body> </html> </f:view>
Please note the enctype of the h:form. This is required to be able to POST binary data. Also note that the download link makes use of the FileServlet. Make sure that it points to the same directory as where the file is uploaded. You can configure it as an init-param.
Here is how the appropriate backing bean (request scoped) look like:
package mypackage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import javax.faces.application.FacesMessage; import javax.faces.context.FacesContext; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.myfaces.custom.fileupload.UploadedFile; public class MyBean { // Init --------------------------------------------------------------------------------------- private UploadedFile uploadedFile; private String fileName; // Actions ------------------------------------------------------------------------------------ public void submit() { // Just to demonstrate what information you can get from the uploaded file. System.out.println("File type: " + uploadedFile.getContentType()); System.out.println("File name: " + uploadedFile.getName()); System.out.println("File size: " + uploadedFile.getSize() + " bytes"); // Prepare filename prefix and suffix for an unique filename in upload folder. String prefix = FilenameUtils.getBaseName(uploadedFile.getName()); String suffix = FilenameUtils.getExtension(uploadedFile.getName()); // Prepare file and outputstream. File file = null; OutputStream output = null; try { // Create file with unique name in upload folder and write to it. file = File.createTempFile(prefix + "_", "." + suffix, new File("c:/upload")); output = new FileOutputStream(file); IOUtils.copy(uploadedFile.getInputStream(), output); fileName = file.getName(); // Show succes message. FacesContext.getCurrentInstance().addMessage("uploadForm", new FacesMessage( FacesMessage.SEVERITY_INFO, "File upload succeed!", null)); } catch (IOException e) { // Cleanup. if (file != null) file.delete(); // Show error message. FacesContext.getCurrentInstance().addMessage("uploadForm", new FacesMessage( FacesMessage.SEVERITY_ERROR, "File upload failed with I/O error.", null)); // Always log stacktraces (with a real logger). e.printStackTrace(); } finally { IOUtils.closeQuietly(output); } } // Getters ------------------------------------------------------------------------------------ public UploadedFile getUploadedFile() { return uploadedFile; } public String getFileName() { return fileName; } // Setters ------------------------------------------------------------------------------------ public void setUploadedFile(UploadedFile uploadedFile) { this.uploadedFile = uploadedFile; } }
Note: make "c:/upload" at least configureable. Maybe as a property in a propertiesfile which could also be shared by the FileServlet.
Back to top
Copyright - There is no copyright on the code. You can copy, change and distribute it freely. Just mentioning this site should be fair.
(C) February 2008, BalusC
224 comments:
«Oldest ‹Older 201 – 224 of 224Hi BalusC! This is working like a charm. What is the best solution if you have file upload as a part of another form or in the same form where is plenty other data to submit as well? I have a form where is 10 fields and one of them is file uploading. I think that only one form is possible. Any nice solution to that? I think that I just have to make one submit and do everything at the same time, upload file, take the name of the file and path and insert it to another formBean and call controller ja insert the data to db? Basically the problem is that I have about 10 forms where is uploading as a part, is there any nice way to include uploading to every page so that I don't need to repeat the same code in many places?
After submit the request or page refresh, how to keep the file name in the box.
after submit the request or page refresh, how to keep the file name in the box.
Hi Balu,
How can i retain the file name in the box after save the file.
Hi I am able to do upload but i need something like when i upload file one of the entity feild must be updated with text.
Here is my code
Do let me know wt possibly i am doing wrong?
CiomemberEdit.xhtml
Member photo
My File upload bean
publicvoid listener(UploadEvent event) throws Exception{
memberHome memberinstance = new memberHome();
memberinstance.setphoto(item.getFileName());
}
My Home entity
public void setphoto(String image)
{
log.info("In method set photo");
imagename = image;
image = "file";
getInstance().setMemberPhoto(image);
update();
}
When successfully upload a file using your suggested coding, an intermediary file will be created at path defined at uploadRepositoryPath
How to clean up this file without interrupt the online service?
Hai BAlusC...
I tried the same code but when i add the jar files commons-io-1.3.2.jar and tomahawk-1.1.10.jar to the libraries,im getting a error message in netbeans7.2
.
.
Error occurred during deployment: Exception while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: java.lang.RuntimeException: com.sun.faces.config.ConfigurationException:
Source Document: jar:file:/C:/Users/Sandeep/Documents/NetBeansProjects/Upload/build/web/WEB-INF/lib/tomahawk-1.1.10.jar!/META-INF/faces-config.xml
Cause: Class 'org.apache.myfaces.webapp.filter.ServeResourcePhaseListener' is missing a runtime dependency: java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory. Please see server.log for more details.
C:\Users\Sandeep\Documents\NetBeansProjects\Upload\nbproject\build-impl.xml:1027: The module has not been deployed.
See the server log for details.
.
.
.
Can u pls heip in in resolving it
HI Balus ,
One quick question . Is there any way other than using tomahawk for file upload.?
Hi BalusC,
im using primefaces fileupload, when i try to upload a file from local to a shared folder on a server, i get this error: "Logon failure: unknown user name or bad password".
What would you recommend to solve that problem,
thanks so much
Hi BalusC
i have an issue , i have tried your code with Websphere portal server7
and RAD 8.5 ,i got following error
and i am not able to execute can you please help.
"[9/14/13 14:50:08:144 IST] 00000034 webcontainer E com.ibm.ws.webcontainer.WebContainer handleRequest SRVE0255E: A WebGroup/Virtual Host to handle /fileupload2/fileupload.jsp has not been defined."
Hi BalusC
Could you please post the normal upload using plain Java code
Sha
Hi BalusC
Could you please post the normal upload using plain Java code
Sha
Hi, my problem is the t:inputFileUpload is not displaying in the page. Have you any idea what can be the problem?? Thank you
I study this topic, build and deploy my project. But when I browse the file for uploading,there's no action in backing bean, uploading file is not work. Please help.
i am using netbean 7.3.1 and glassfish 3 so please help how to uplaod the default image in jsf latter these image is replace newly upload image
this is mt java code
public class FileUploadController {
private String destination="D:\\tmp\\";
/**
* Creates a new instance of FileUploadController
*/
public FileUploadController() {
}
public void upload(FileUploadEvent event)
{
FacesMessage msg = new FacesMessage("Success! ", event.getFile().getFileName() + " is uploaded.");
FacesContext.getCurrentInstance().addMessage(null, msg);
try {
copyFile(event.getFile().getFileName(), event.getFile().getInputstream());
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void copyFile(String fileName, InputStream in) {
try {
// write the inputStream to a FileOutputStream
OutputStream out = new FileOutputStream(new File(destination + fileName));
int read = 0;
byte[] bytes = new byte[1024];
while ((read = in.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
in.close();
out.flush();
out.close();
System.out.println("New file created!");
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
this is my xhtml file code
this is web.xml file i am maaping of filter in this file
filter-name>PrimeFaces FileUpload Filter
org.primefaces.webapp.filter.FileUploadFilter
PrimeFaces FileUpload Filter
Faces Servlet
filter-name>PrimeFaces FileUpload Filter
org.primefaces.webapp.filter.FileUploadFilter
PrimeFaces FileUpload Filter
Faces Servlet
filter-name>PrimeFaces FileUpload Filter
org.primefaces.webapp.filter.FileUploadFilter
PrimeFaces FileUpload Filter
Faces Servlet
in above code the image not show on destination place and not show on our page ?
Hi Balus,
Fists of all my excuses i am braziliam and i don't espeak and write english well.
I spend tree weks trying do do a fileupload, i tested aboout 30 examples, jsf 2.2 inputfile, primefaces fipeupload ... None of them runs as suposed. Then a finally found your example tomahawk, e all Works ok. Thank you.
Hi Balus,
I have uploaded the file.It is working fine but when i through a validation error from backing bean.My file becomes null but all the other fields are populated.Is that the default behavior of file upload.Can I keep the file intact even after the validation error.
Thanks
Anu
Hello Baluc,
Thanks for the post,it was really helpful.
I have just one issue-
On page refresh,same file is being uploaded again. I even setUploadedFile(null) at the end of submit method but still doesn't work.
Any help would be really appreciated.
i initialize the t:inputfileupload in my html pages its working perfectly. In same page i initialize the another t:inputfileupload its block the fileupload method. its working for only one file upload in page.i want to initialize t:inputfileupload one more component please help me
both files for different category based upon menu
Thanks...
But I have a problem. The setter method is never called, then a NPE raised.
What I forgot?
Use "Long Path This very useful if you are having problems
in deleting, unlocking, copying and even renaming files, also very easy.
same code worked in jboss 4.2.3 GA. and recently we migrate jboss to wildfly 26 deployed on it we use jsf 1.2, myfaces,java 8 servlet 2.5. inputfileuplod bean mapped setter and getter get null value.
Post a Comment