O'Reilly Multipart Request Parser

2djohn
2djohn used Ask the Experts™
on
I don't know if anyone would have tried something like this:

I am using the MultipartParser to find a non-file parameter value, as follows:

protected String getParameterValueFromMultipart( HttpServletRequest request, String param, int maxSize ) throws Exception {
         
MultipartParser parser = new MultipartParser( request, maxSize );

Part part;
         
while ( ( part = parser.readNextPart() ) != null ) {
         
   if ( part.isParam() ) {
               
      String name = part.getName();
      ParamPart paramPart = (ParamPart) part;
      String value = paramPart.getStringValue();    
      if ( name.equals( param ) ) return value;
    }
}
return null;
}

But if I do this, and I get the value I want, and then I try to use the O'Reilly code (MultipartRequest and MultipartParser)to save a file using this same request, I get a "Corrupt Form Data" exception from the parser next time around.

Is there a bug in this code that is leaving some resource open?  Or am I doing something wrong?

Thanks!
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Top Expert 2016

Commented:
Well, you don't show the bit where you create a new output stream on a new file.

>>
String value = paramPart.getStringValue();    
if ( name.equals( param ) ) return value;
>>

would be better:

if ( name.equals( param ) ) return paramPart.getStringValue();

or you may have unnecessary evaluations.


Top Expert 2016

Commented:
>>or you may have unnecessary evaluations.

What i meant was you could be creating strings unnecessarily.
Distinguished Expert 2018

Commented:
 Can you post the full stack trace as well some of your code that you use the Multipart class?
Exploring ASP.NET Core: Fundamentals

Learn to build web apps and services, IoT apps, and mobile backends by covering the fundamentals of ASP.NET Core and  exploring the core foundations for app libraries.

Top Expert 2016

Commented:
This is what i've got now:

<?xml version="1.0"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" exclude-result-prefixes="#default" version="1.0">


<xsl:output method="html"/>



<xsl:template match="html:img">
  <img src="XXXXXXXXXXXXXXXXXXXXXXXXXXXX" />
</xsl:template>


<xsl:template match="*">
     <xsl:copy>
          <xsl:copy-of select="@*"/>
          <xsl:apply-templates/>
     </xsl:copy>
</xsl:template>

     
</xsl:stylesheet>



Errors are:

Prefix must resolve to a namespace: html
Top Expert 2016

Commented:
Sorry - posted in the wrong question!!
Distinguished Expert 2018

Commented:
 Np.. By the way should this: xmlns="http://www.w3.org/1999/xhtml" not be: xmlns:html="http://www.w3.org/1999/xhtml"

Author

Commented:
Sure- here is some more of what is going on- and don't mind the sloppy code for now- it is a work in progress :)

I am not sure what you meant about "creating the new output stream on the new file"?

Here is a little more of the story:  in an ActionRouter, I may or may not want to save a file that is part of a multi part request, based on one of the parameters in the multipart request.

//first call the function mentioned above
String album = getParameterValueFromMultipart( request, "album", 10*1024*1024 );

if ( album == null ) throw new ServletException( "album parameter not valid" );

//if the parameter is valid, then save the file
String saveDir = getDirectory( servlet );
MultipartRequest multi = new MultipartRequest( request, saveDir, 10*1024*1024 ); // 10MB

// and here is the top of the stack trace:
Stack trace: java.io.IOException: Corrupt form data: premature ending
at com.oreilly.servlet.multipart.MultipartParser.<init>(MultipartParser.java:166)

at com.oreilly.servlet.multipart.MultipartParser.<init>(MultipartParser.java:94)

at com.oreilly.servlet.MultipartRequest.<init>(MultipartRequest.java:219)

at com.oreilly.servlet.MultipartRequest.<init>(MultipartRequest.java:106)

Does that help at all?  Maybe I am not closing and opening streams properly?  I figured that would be done by what is there in the O'REilly classes.

Thanks!
Distinguished Expert 2018

Commented:
 Are you using Tomcat? If yes take a look here: http://www.servlets.com/soapbox/bugs.html
Distinguished Expert 2018

Commented:
 Are you using Tomcat? If yes take a look here: http://www.servlets.com/soapbox/bugs.html

Author

Commented:
I am using Tomcat 4.0.4, so I guess those bugs don't apply.  Although that is in the ballpark.  I am able to dave my file with the MultipartRequest class without problem- if I do not use the MutipartParser to read the parameters first.  I'm sorry- I should have said that from the start!!!!!
Distinguished Expert 2018

Commented:
 Well, theer are differences between MultipartRequest and MultipartParser. So if one works I';d suggest you stick with it.

  You might find some more info about your problem here:

http://www.servlets.com/cos/faq.html

  Apart from that I do not have any more ideas. I;d strongly suggest you try some other web server as well. Just for the sake of it.
Top Expert 2016

Commented:
Can we back up a bit? As far as i can remember from one of your earlier postings, you use case was:

1. Get a file that's been uploaded
2. Get a parameter for a new name for the file
3. If 2 exists, save it with that name instead of its original.

Is that still your use case, or have you changed it?

Author

Commented:
That is basically the case- the only thing is that I am trying to NOT save the file unless I have the param- which means that I cannot create a MultipartRequest, which automatically saves the file- then I would have to delete it later which is messy.

I realise they are different classes, but I think I am using them properly- the Parser just gives you a finer degree of control.

I will give you the points either way- I am just going to check some of the links you have sent and see what I can find out...

Thanks
Top Expert 2016
Commented:
In that case, the implementation seems to be straightforward:

1. Create a MultipartParser from the request
2. Iterate the parts
3. Save a reference to the Part if it's a FilePart
4. If there's a ParamPart and the param is the new file name, save the reference.
5. Post iteration, if both FilePart and ParamPart are correct, get an input stream on the FilePart and write a new file with the name as the ParamPart parameter.

Author

Commented:
I was just working on the same idea!  I will let you know how it goes and get back to you later- I wonder why the two are not working together- maybe that is for another day.  Thanks.
Top Expert 2016

Commented:
You're almost there with the code you first posted.
Top Expert 2016

Commented:
Girionis:

>>
By the way should this: xmlns="http://www.w3.org/1999/xhtml" not be: xmlns:html="http://www.w3.org/1999/xhtml"
>>

if you're interested, this is at http://www.experts-exchange.com/Web/Web_Languages/XML/Q_20400506.html
Mick BarryJava Developer
Top Expert 2010

Commented:
It looks like you're trying to parse the same request stream twice. Your first parser reads the request data checking for parameters, then when the MultiPart request goes to parse the request stream it is already midstream so it fails.

Author

Commented:
Objects,

What action should I take to "close" or "reset" the stream- if I was going to go about it that way?
Mick BarryJava Developer
Top Expert 2010

Commented:
I'm not sure you can, the request is not file a file that you can open, close and reopen. It is a stream of bytes sent from the client to the server, and once they are read that's it.
Mick BarryJava Developer
Top Expert 2010

Commented:
I think if you want to handle the parsing yourself then you have to handle *all* the parsing.
Mick BarryJava Developer
Top Expert 2010

Commented:
Something like:

boolean needFile = false;
while ( ( part = parser.readNextPart() ) != null ) {
         
  if ( part.isParam() ) {
             
     String name = part.getName();
     ParamPart paramPart = (ParamPart) part;
     String value = paramPart.getStringValue();    
     // Set needFile appropriately
   }
   else if (part.isFile() && needFile) {
     // Save file
   }
}

Author

Commented:
Actually- that is what I have switched to now.  The only thing is that it is not actually writing the bytes to the file propery.

I am going to award the points to CEHJ, but I am also going to create a new question to give some points to "objects" titled "A question for objects."

Then I will post another question on the parser if I can't figure out the problem there!

Thanks everyone.

Commented:
I am having the same problem.

It seems, that when you create the

MultipartFormDataRequest mrequest = new MultipartFormDataRequest(request)

the request changes. So, you can't parse the request twice, because it throws an exception..

My scenario is as follows:

method1(HttpServletRequest r) {
MultipartFormDataRequest = new MultipartFormDataRequest(r);
}

method2(HttpServletRequest r) {
MultipartFormDataRequest = new MultipartFormDataRequest(r);
}

If you invoke method1 and the method2, passing the same request object, method2 throws and exception (premature ending).

Does anybody knows why doed this happens ?
Has something to do with the Multipart Object i'm using ?

Diego.

Commented:
I am having the same problem.

It seems, that when you create the

MultipartFormDataRequest mrequest = new MultipartFormDataRequest(request)

the request changes. So, you can't parse the request twice, because it throws an exception..

My scenario is as follows:

method1(HttpServletRequest r) {
MultipartFormDataRequest = new MultipartFormDataRequest(r);
}

method2(HttpServletRequest r) {
MultipartFormDataRequest = new MultipartFormDataRequest(r);
}

If you invoke method1 and the method2, passing the same request object, method2 throws and exception (premature ending).

Does anybody knows why doed this happens ?
Has something to do with the Multipart Object i'm using ?

Diego.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial