Java Servlets Using MultipartConfig - java

I am using a catch-all servlet and passing the request object along to other internal framework classes. Its how my application is designed. The reasons are beyond the scope of this question.
#WebServlet(name="RequestHandler", urlPatterns="/*")
I am trying to do file uploading from the browser using multipart-form-data:
<form action="" method="POST" enctype="multipart/form-data">
<input type="file" name="file"/>
<input type="submit" name="videoUpload" value="Upload"/>
</form>
And the only way to actually pass the file data along to the server is to annotate the servlet with:
#MultipartConfig
If I annotate my catch-all servlet, everything works fine but its not very often at all that I actually need to use the file uploading functionality.
Option 1: Leave it alone.
Does leaving the annotation cause unnecessary overhead even though most of the requests don't use it?
Option 2: Add it programatically?
Is there a way to programatically add the annotation if the form type of multipart is detected?
Option 3: Use the annotation elsewhere.
What about using the annotation in a separate class (i'm assuming it needs to be present before the request object is actually created...)?

It is ok if you dont add '#MultipartConfig' annotation. You can determine programmatically if the content is multipart or not:
String form_field="";
FileItem fileItem = null;
if (ServletFileUpload.isMultipartContent(request)) {
ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory());
try {
fileItemsList = servletFileUpload.parseRequest(request);
} catch (FileUploadException ex) {
out.print(ex);
}
String optionalFileName = "";
Iterator it = fileItemsList.iterator();
while (it.hasNext()) {
FileItem fileItemTemp = (FileItem) it.next();
if (fileItemTemp.isFormField()) {
if (fileItemTemp.getFieldName().equals("form_field")) {
form_field = fileItemTemp.getString();
}
} else {
if (fileItemTemp.getFieldName().equals("file")) {
fileItem = fileItemTemp;
}
}
}
}
If ServletFileUpload.isMultipartContent(request) is false then you can retrieve form parameters in general way by request.getParameter. I have used apache file upload in the example.

Related

Multipart POST request doesn't contain the file uploaded

I want to extend an existing application with a drag and drop file upload feature. The application is built upon Jetty + Wicket. DropzoneJS seems a good way to go. Dropzone provides all front-end work, I just have to wire it up to the back-end.
More easily said than done, as it turns out. First, I created a test application with the Wicket quickstart. I added dropzone to the HomePage:
<!DOCTYPE html>
<html>
<head>
<script src="https://rawgit.com/enyo/dropzone/master/dist/dropzone.js"></script>
<link rel="stylesheet" href="https://rawgit.com/enyo/dropzone/master/dist/dropzone.css">
</head>
<body>
<form action="/upload" class="dropzone"></form>
</body>
</html>
Dropzone is simply included from its repository. On the server, I mounted a resource reference at /upload:
public class FileUploadResourceReference extends ResourceReference
{
public FileUploadResourceReference(String name)
{
super(FileUploadResourceReference.class, name);
}
#Override
public IResource getResource()
{
return new FileUploadResource();
}
}
FileUploadResource will handle processing of uploaded files:
public class FileUploadResource extends AbstractResource
{
#Override
protected ResourceResponse newResourceResponse(Attributes attributes)
{
ServletWebRequest request = (ServletWebRequest) attributes.getRequest();
try
{
MultipartServletWebRequest multipartRequest = request
.newMultipartWebRequest(Bytes.megabytes(100), "ignored");
Map<String, List<FileItem>> files = multipartRequest.getFiles();
List<FileItem> fileItems = files.get("file");
for (FileItem fileItem : fileItems)
{
saveFile(fileItem);
}
}
catch (FileUploadException e)
{
e.printStackTrace();
}
return null;
}
private void saveFile(FileItem fileItem)
{
// not implemented
}
}
Now here's the problem, when uploading files, Dropzone sends a POST-request to my http://localhost:8080/upload. The request is recognized as a multipart request, but the file parameter is absent. A null pointer exception is thrown entering the for-loop:
java.lang.NullPointerException
at com.test.FileUploadResource.newResourceResponse(FileUploadResource.java:31) ~[classes/:?]
at org.apache.wicket.request.resource.AbstractResource.respond(AbstractResource.java:629) ~[wicket-core-7.4.0.jar:7.4.0]
at org.apache.wicket.request.handler.resource.ResourceRequestHandler.respond(ResourceRequestHandler.java:105) ~[wicket-core-7.4.0.jar:7.4.0]
at org.apache.wicket.request.handler.resource.ResourceReferenceRequestHandler.respond(ResourceReferenceRequestHandler.java:108) ~[wicket-core-7.4.0.jar:7.4.0]
I can't figure out what's going on here. According to the Dropzone website, the form declaration should be fine. A bug in Dropzone perhaps? Seems unlikely. Some Jetty configuration parameter that is denying multipart form requests? Seems highly unlikely, at least I've never heard of it.
You can find full source code of my test app on GitHub.
You miss one method call - multipartRequest.parseFileNames().
You need to do it before #getFiles().
See http://wicketinaction.com/2012/11/uploading-files-to-wicket-iresource/

How to bypass struts2 interceptors on file upload

I wrote a simple page with a form to upload a file and a jsp to handle that file.
My problem is that when the file is uploaded, the request object is handled by Struts interceptors and when it comes to the jsp page it is already "consumed", so the calls to read the request with methods such as "ServletFileUpload.parseRequest()" returns empty lists.
I have already found a working solution, but this needs to restart Tomcat, and since the page has to be added on the production server, it would be so much better if there is a way to not restart it.
For now, what I tried and worked is this:
1) in struts.xml i added
<include file="custom/struts-custom.xml"/>
2) in the struts-custom.xml i wrote:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.action.excludePattern" value="/path_to_my_jsp/page.jsp"/>
</struts>
With this i can upload the file bypassing struts interceptors.
Is there a better / cleaner solution? as i said, the best would be a solution that doesn't need to restart the application server.
Even if i don't think that the problem is related to code, i will post it.
page.html:
<form action="upload.jsp" method="post" enctype="multipart/form-data" TARGET="Report_Down"
onSubmit="if(document.getElementById('file1').value == '') return false;">
Input File <input type="file" name="file1" id="file1">
<input type="submit" value="Upload">
</form>
upload.jsp:
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (!isMultipart) {
return;
}
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(1024 * 1024 * 2);
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
String uploadFolder = getServletContext().getRealPath("")
+ File.separator + DATA_DIRECTORY;
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setSizeMax(1024 * 1024);
try {
List items = upload.parseRequest(request);
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (!item.isFormField()) {
try {
String fileName = new File(item.getName()).getName();
String filePath = uploadFolder + File.separator + fileName;
File uploadedFile = new File(filePath);
item.write(uploadedFile);
//do something...
}
catch(Exception e) {
//...
}
}
}
getServletContext().getRequestDispatcher(forwardUrl).forward(
request, response);
} catch (FileUploadException ex) {
throw new ServletException(ex);
} catch (Exception ex) {
throw new ServletException(ex);
}
Thank you in advance :)
What do you mean with the request is consumed ? The request passes through the Interceptor Stack up to the Action, and is still there.
If, for some reason (and you should not have one, when doing a simple upload of a file), you need to run code out of the framework mechanisms (Actions, Interceptors etc), you can use a Servlet.
By the way, this is the correct way of uploading a file in Struts2, and your problem is mostly related to
the maximum file/request cap hit;
a wrong definition of the interceptor stack.
I bet on n.1, but if this still haven't solved your problem, post more details about your struts.xml.
Also remember to avoid using scriptlets (as already suggested by Boris) and to never call JSPs directly: always pass through an Action.

Retrieve file from POST request with NanoHttpd

I am trying to use the NanoHttpd library to upload files to my Android server by using a POST request from a form. I do receive the POST request on the server side. My question is how to retrieve the file from the POST request so I can save it somewhere in the device memory.
the form :
<form action='?' method='post' enctype='multipart/form-data'>
<input type='file' name='file' />`enter code here`
<input type='submit'name='submit' value='Upload'/>
</form>
the serve method :
#Override
public Response serve (IHTTPSession session) {
Method method = session.getMethod();
String uri = session.getUri();
if (Method.POST.equals(method)) {
//get file from POST and save it in the device memory
}
...
}
Last night i found solution it's very easy to upload file....
First you have manage 'TempFileManager'. It's handle temp file directory so it' create file and delete automatically after your work finish like copy,read,edit,move etc...
server.setTempFileManagerFactory(new ExampleManagerFactory());
So now you not have manage temp file it's work automatically...
Manage post request like this
private Response POST(IHTTPSession) {
try {
Map<String, String> files = new HashMap<String, String>();
session.parseBody(files);
Set<String> keys = files.keySet();
for(String key: keys){
String name = key;
String loaction = files.get(key);
File tempfile = new File(loaction);
Files.copy(tempfile.toPath(), new File("destinamtio_path"+name).toPath(), StandardCopyOption.REPLACE_EXISTING);
}
} catch (IOException | ResponseException e) {
System.out.println("i am error file upload post ");
e.printStackTrace();
}
return createResponse(Status.OK, NanoHTTPD.MIME_PLAINTEXT, "ok i am ");
}

Accessing uploaded file in Apache Tapestry page

I'm using Apache Tapestry v5.3.7 and I already use the normal Tapestry upload component in a form. For a better user experience I try now to integrate Dropzone.js in a normal Tapestry page without any form. The JavaScript integration works fine. The uploaded file data are transferred to my server with a post request and I can access the request with all of its parameters.
My question is now how can I access the binary data of the uploaded file (maybe as InputStream) to save them in my system? I already injected the http request but getInputStream returns a empty stream.
Thanks for any suggestions
/** Code snippet of page java part */
...
#Inject
protected HttpServletRequest _request;
public void onActivate (String rowId) {
String fileName=_request.getParameter("file");
try {
InputStream is=_request.getInputStream();
// if I do read from is it returns -1
// :-(
doSomeSaveStuff(is); // dummy code
}
catch(Exception e) {
e.printStackTrace();
}
}
...
Here's one way to do it:
In template:
<t:form t:id="testForm" class="dropzone">
</t:form>
In page.java
#Inject
MultipartDecoder multipartDecoder;
#Component(id = "testForm")
private Form testForm;
#Inject
RequestGlobals requestGlobals;
void onSubmitFromTestForm() throws ManagerException {
System.out.println("test form invoked");
HttpServletRequest r = requestGlobals.getHTTPServletRequest();
UploadedFile u = multipartDecoder.getFileUpload("file");
The uploaded file contains what you uploaded and you can work with it the way you want.
Note: the HttpServletRequest::getParameterMap() , told me that the handle to to the file is called file which is how I know that passing file to getFileUpload makes the decoder correctly parse the multipart/post

Uploading a file in Java Servlet

I have a Java Dynamic Web Project, and I'm using TomCat v7.0.
I am new to web projects and I didn't quite understand how I can upload a file in one of my jsp pages. Since my project is intended to be only local, I thought I could use a multipart form in which the person would choose the file (and this part goes fine) and later retreive the file path from my Servlet. I can't complete this part though, it appears to only give me the name of the file, not its entire path.
Can anyone point me to the right direction? I've read several posts about Apache File Upload and retreiving information from the multipart form but nothing seems to help me.
How can I get the file path from a form or alternatively how can I get the uploaded file to use in my Java classes?
Thanks in advance.
.jsp:
<form method="post" action="upload" enctype="multipart/form-data">
<input type="file" name="filePath" accept="application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"></input>
<input type="submit" value="Enviar"></input>
</form>
Java Servlet:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
PrintWriter out = response.getWriter();
out.println("<html><body>");
try
{
List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
for (FileItem item : items)
{
if (item.isFormField())
{
// Process regular form field (input type="text|radio|checkbox|etc", select, etc).
String fieldname = item.getFieldName();
String fieldvalue = item.getString();
out.println("<h1>"+fieldname+" / "+fieldvalue+"</h1>");
}
else
{
// Process form file field (input type="file").
String fieldname = item.getFieldName();
String filename = item.getName();
InputStream filecontent = item.getInputStream();
String s = filecontent.toString();
out.println("<h1>"+s+" / "+filename+"</h1>");
item.write(null);
}
}
}
catch (FileUploadException e)
{
throw new ServletException("Cannot parse multipart request.", e);
}
catch (Exception e)
{
e.printStackTrace();
}
out.println("</body></html>");
}
Not providing the file path is a security feature of the browser.
You have the file contents available in your code (InputStream filecontent) so you could use that or use one of the convenience methods on FileItem, e.g.
item.write(new File("/path/to/myfile.txt"));

Categories