Follow up on MultipartParser

2djohn
2djohn used Ask the Experts™
on
GIVEN THIS:

File file = new File( SOME VALID DIRECTORY );
long size = 0;
MultipartParser mp = new MultipartParser( request, 10*1024*1024, true, true, null );
Part part;

This writes to file: (A)

while ( ( part = mp.readNextPart() ) != null ) {

    if ( part.isFile() ) {
        filePart = (FilePart)part;
        size = filePart.writeTo( file );
    }
}

But this does not: (B)

while ( ( part = mp.readNextPart() ) != null ) {

    if ( part.isFile() ) {

        filePart = (FilePart)part;
    }
}

// do some checking

size = filePart.writeTo( file );

In case B, zero bytes are written to file- something to do with the way the parser is reading the buffer no doubt.  Is there some way I could write this so that I could write to file even after we have left that loop?  Some way to make a copy of that filePart so that even though the parser keeps reading the buffer- I could use that filePart later?

Thanks!
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Mick BarryJava Developer
Top Expert 2010

Commented:
You could read it into memory, but if the file is a bit large this could get expensive.
Mick BarryJava Developer
Top Expert 2010

Commented:
ByteArrayOutputStream out = new ByteArrayOutputStream();
filePart.writeTo(out);
Mick BarryJava Developer
Top Expert 2010

Commented:
Of course if you've already read the parameters required to make the decision whether save file or not, then you can simply write to file directly.
PMI ACP® Project Management

Prepare for the PMI Agile Certified Practitioner (PMI-ACP)® exam, which formally recognizes your knowledge of agile principles and your skill with agile techniques.

Author

Commented:
Is it guaranteed that the order in which parameters are added to a form is the order in which they will be parsed?  If so then I think your last comment is the only viable solution, minding your warning about reading the file into memory.
Mick BarryJava Developer
Top Expert 2010

Commented:
Not sure, and is probably dependant on the client.
You could of course handle it directly if you get the parameters first, and if not you could handle it alternatively (I'd just write it to disk and delete if not required).
Top Expert 2016

Commented:
>>Is there some way I could write this so that I could write to file even after we have left that loop?

Simply save a reference to it:


FilePart savedFilePart = null;
String FILE_SOUGHT = "something.text";
while ( ( part = mp.readNextPart() ) != null ) {

   if ( part.isFile() ) {

       if( ( (FilePart) part).getFileName().equals(FILE_SOUGHT) ){
        savedFilePart = part;
       }
   }
}

// do some checking

if ( savedFilePart != null ){
     size = filePart.writeTo( file );
}

Author

Commented:
CEHJ- that is the first thing that I tried, but it does not work.  I am not exactly sure why, not being a Java Guru, but it seems to me that the reference you save is lost as part the parser reads in the next part.  If you tried to write with the "savedFilePart.writeTo(file)" (which is what I think you meant above), you will write zero bytes.

Actually I would love to know the exact reason for this!  Objects was saying that you would have to read it into memory, which intuitively sounds right to me.
Top Expert 2016
Commented:
Yes, he's right - this is what it says in the docs:

"Don't try to store a FilePart object for later processing because by then their content will have been passed by."

So, if you wanted to save each part, you could create a class to contain each, such as:

class SavedFilePart {
  String filePath;
  String fileName;
  StringBuffer data;
 
  public SavedFilePart(FilePart part,String filePath,String fileName){
    data = new StringBuffer();
    this.filePath = part.getPath();
    this.fileName = part.getFileName();
    BufferedInputStream in = part.getInputStream();
    // read it into the StringBuffer
    int c = -1;
    while ((c = in.read()) > -1){
      data.append(c);
    }
  }
}

Author

Commented:
This is fantastic information CEHJ and objects! Thank you very much!  I will once again give points to both people- I won't split them I will give both the 100.  One more question before doing that:  CEHJ what docs were you referring to and where in them did you see that?  I was looking for something like that.

Thanks again.
Top Expert 2016

Commented:
http://www.servlets.com/cos/javadoc/com/oreilly/servlet/multipart/FilePart.html.

The point is that these FileParts have been got by reading a stream so it should have been quite obvious to me :-)

It should be part.getFilePath() in my code incidentally.

Author

Commented:
Objets- I will post another question with you name on it for a hundred points as well- you know the drill.

Thanks guys.
Top Expert 2016

Commented:
Cheers!
Mick BarryJava Developer
Top Expert 2010

Commented:
Thats what I originally said (just a bit longer).
My only concern about that was that if the file was large then you run out of memory:

filePart.writeTo(out);

Author

Commented:
I understand that objects- the other comments simply clarified things for me a little.  In fact I think I will not do it that way because of memory concerns.  But at least I have the option!
Top Expert 2016

Commented:
You could of course keep a count of the bytes read and get out if it exceeds a limit you've decided upon.
Top Expert 2016

Commented:
btw, the code in the loop should have been

data.append((char)c);

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