Issue
I am trying to upload an excel file using servlet on Tomcat server using Eclipse IDE. I have written the following code to take the file via an HTML form. There are no errors on the program but the console keeps throwing the exception file not found.
try {
ServletFileUpload sf=new ServletFileUpload(new DiskFileItemFactory());
List<FileItem> multifiles = sf.parseRequest(request);
String file="";
for(FileItem item : multifiles)
{
file =item.getName();
item.write(new File("C:\\Users\\khuha\\eclipse-workspace\\firstDemo\\"+ file));
}
FileInputStream fis= new FileInputStream(file);
XSSFWorkbook wb=new XSSFWorkbook(fis);
System.out.println("Enter the sheet you want to search in: ");
Scanner sc= new Scanner(System.in);
int n= sc.nextInt();
XSSFSheet sheet=wb.getSheetAt(n-1);
Iterator<Row> itr=sheet.iterator();
There is further code to process the file and I was expecting an output in the console but instead I got the below mentioned Exception:
INFO: Server startup in 17359 ms
java.io.FileNotFoundException: IT_return_FY_22.xlsx (The system cannot find the file specified)
at java.base/java.io.FileInputStream.open0(Native Method)
at java.base/java.io.FileInputStream.open(FileInputStream.java:216)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:111)
at attendanceApp.fileUpload.doPost(fileUpload.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:682)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:765)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:543)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:698)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:367)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:639)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:882)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1693)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:833)
java.io.FileNotFoundException: Details.xlsx (The system cannot find the file specified)
at java.base/java.io.FileInputStream.open0(Native Method)
at java.base/java.io.FileInputStream.open(FileInputStream.java:216)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:111)
at attendanceApp.fileUpload.doPost(fileUpload.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:682)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:765)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:543)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:698)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:367)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:639)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:882)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1693)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:833)
How do I resolve the exception so that my file gets processed and I am able to perform the required functions on it?
I need to get rid of the file after the operations are done. HOw can I achieve that?
Solution
You're writing the file to
item.write(new File("C:\\Users\\khuha\\eclipse-workspace\\firstDemo\\"+ file));
and you're reading the file from whereever your current directory is.
FileInputStream fis= new FileInputStream(file);
If both don't match, the file won't be found where it's looked for.
On top, you're looping through potentially many files (in your for
loop), and then only work on the last one written to disk. So the code in your question, when just corrected for the file's location, will only work for a single uploaded file.
Also, you're opening yourself up to some nasty attack by string-concatenating the directory to the file name - imagine someone sends you a file by the name of "../../Desktop/some-file.exe"
: You should rather use the File
constructor that takes an explicit directory, and the file name - and likely also use an explicit temporary directory and make sure it's deleted after you're done with it.
Also, depending on the implementation of FileItem (as you don't give us the package/version): Make sure you don't need to flush/close it to make sure that all the content is available on disk before reading it again.
How to write the code correctly (as you ask in the comment to this answer) depends a bit on what you're actually doing with the content - and I can't (or won't) give a definitive answer. But in pseudocode, one option that you can start with, is this:
List<FileItem> multifiles = sf.parseRequest(request);
String fileName="";
for(FileItem item : multifiles)
{
fileName =item.getName();
File file = File.createTempFile(fileName, null); // no more explicit location, no more path traversal attack.
item.write(file);
file.deleteOnExit(); // if something goes wrong: Get rid of file at shutdown
doSomethingWithFileContent(file); // for you to implement
file.delete(); // if nothing goes wrong: We don't need the file from now on.
}
Then implement the doSomethingWithFileContent (which takes a java.io.File
, not a String
file name as parameter).
Note that you can't expect System.out
and System.in
to be useful in a web application: That data needs to come as parameter with the request and correcting this would be way beyond the scope of this question.
Also, this is not the solution to your problem. Ideally, the content wouldn't even touch the disk but you can absolutely work with it in memory, without writing a file to begin with.
Answered By - Olaf Kock
Answer Checked By - Mildred Charles (JavaFixing Admin)