Re: uploading file requires immediate serialization location?
Sorry, I should have said If the bean goes away, then so does the only reference you'll get to the file that holds the uploaded data. The FormFile object, which contains the relevant information, will go away when the bean goes away (unless you have another reference to it, of course). The FormFile does not contain the actual uploaded data, just the name of the file it was saved in. -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Sunday, June 10, 2001 11:16 PM Subject: Re: uploading file requires immediate serialization location? You wrote... The uploaded data is stored in a temporary file somewhere on disk.The bean is in either request or session scope. If the bean goes away, then so does the file that holds the uploaded data. I thought you said the file was written to disk? Thus the binary is not in the bean. Or is it that the FormFile has all this data and IT is in the bean. So I end up with a file on disk that is in a state of not be associated with anything yet, and whos filename and input field names I have lost when the bean went away. Is that it? If we are keeping the FormFile in the bean, in the session and the FormFile indeed does contain the binary, than this is a bad thing. We should at theleast kill the binary from the FormFile object so we CAN safely put it in the session. (Dont know if I mentioned by weblogic croaks/freaks if the session has too much k in it. - Original Message - From: Martin Cooper [EMAIL PROTECTED] To: [EMAIL PROTECTED]; Jonathan Asbell [EMAIL PROTECTED] Sent: Monday, June 11, 2001 1:55 AM Subject: Re: uploading file requires immediate serialization location? String parameters are not written to a file. Only the bodies of file upload parts are written to disk, and each one to a separate file. The files are written as the input stream (i.e. the request) is processed. Let's say your form has two fields, a textarea called 'myText' and a file input called 'myFile'. After you submit it, and Struts has populated your form bean, you will have: 1) The text from the textarea field is stored in the bean's 'myText' property as a String. 2) The uploaded data is stored in a temporary file somewhere on disk. 3) The 'myFile' property on your bean, which has type FormFile, contains information about the uploaded data (e.g. file name, content type, etc.). The bean is in either request or session scope, as you defined it in your struts-config.xml file. If the bean goes away, then so does the file that holds the uploaded data. Hope this helps. -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Sunday, June 10, 2001 10:48 PM Subject: Re: uploading file requires immediate serialization location? So do you simultaneously write to a file while reading a String parameter when you process a form? What parts of the multipart request do we save in the bean, and in what scope? - Original Message - From: Martin Cooper [EMAIL PROTECTED] To: [EMAIL PROTECTED]; Jonathan Asbell [EMAIL PROTECTED] Sent: Monday, June 11, 2001 1:23 AM Subject: Re: uploading file requires immediate serialization location? Yes, I think you've got it. Just to be clear, though, when you say we need to examine the sections in the header ..., the we here is Struts - you don't need to do anything in your application. Struts makes getParameter() et all work for multipart requests as well as regular requests. What you are seeing in the packages you've looked at is the parsing of a MIME part. The fields in a multipart/form-data request each conform to the specification for a MIME part, and they are separated by a boundary, which is a line containing a pattern defined in a header at the top of the request. Each MIME part consists of a sequence of MIME headers, followed by a blank line, followed by the data for that MIME part, known as the body. A MIME header takes the form header-name: value - for example, Content-type: text/plain. The body is just a bunch of data that conforms to the statements made about it in the headers. Every field in a multipart request is encoded this way. So where a regular query using GET might contain a query string like this: ...author=Martin... a multipart request would represent the same query parameter like this: -0123456789-- Content-disposition: form-data; name=author Martin -0123456789-- For a file upload, the difference is only that the Content-disposition header will include a file name, and the data can be binary if necessary. When a multipart handler processes a request, it is reading the data from
Re: uploading file requires immediate serialization location?
Martin, Hi. Can I pick your brain about an earlier post? I asked what would happen if I have a html:file tag on my form, but without changing the enctype to multipart/form-data? Do you know if I just then get a String containing the filename selected/entered? thanks, Dave Martin Cooper [EMAIL PROTECTED] on 06/11/2001 01:55:07 AM Please respond to [EMAIL PROTECTED] To: [EMAIL PROTECTED], Jonathan Asbell [EMAIL PROTECTED] cc:(bcc: David Hay/Lex/Lexmark) Subject: Re: uploading file requires immediate serialization location? String parameters are not written to a file. Only the bodies of file upload parts are written to disk, and each one to a separate file. The files are written as the input stream (i.e. the request) is processed. Let's say your form has two fields, a textarea called 'myText' and a file input called 'myFile'. After you submit it, and Struts has populated your form bean, you will have: 1) The text from the textarea field is stored in the bean's 'myText' property as a String. 2) The uploaded data is stored in a temporary file somewhere on disk. 3) The 'myFile' property on your bean, which has type FormFile, contains information about the uploaded data (e.g. file name, content type, etc.). The bean is in either request or session scope, as you defined it in your struts-config.xml file. If the bean goes away, then so does the file that holds the uploaded data. Hope this helps. -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Sunday, June 10, 2001 10:48 PM Subject: Re: uploading file requires immediate serialization location? So do you simultaneously write to a file while reading a String parameter when you process a form? What parts of the multipart request do we save in the bean, and in what scope? - Original Message - From: Martin Cooper [EMAIL PROTECTED] To: [EMAIL PROTECTED]; Jonathan Asbell [EMAIL PROTECTED] Sent: Monday, June 11, 2001 1:23 AM Subject: Re: uploading file requires immediate serialization location? Yes, I think you've got it. Just to be clear, though, when you say we need to examine the sections in the header ..., the we here is Struts - you don't need to do anything in your application. Struts makes getParameter() et all work for multipart requests as well as regular requests. What you are seeing in the packages you've looked at is the parsing of a MIME part. The fields in a multipart/form-data request each conform to the specification for a MIME part, and they are separated by a boundary, which is a line containing a pattern defined in a header at the top of the request. Each MIME part consists of a sequence of MIME headers, followed by a blank line, followed by the data for that MIME part, known as the body. A MIME header takes the form header-name: value - for example, Content-type: text/plain. The body is just a bunch of data that conforms to the statements made about it in the headers. Every field in a multipart request is encoded this way. So where a regular query using GET might contain a query string like this: ...author=Martin... a multipart request would represent the same query parameter like this: -0123456789-- Content-disposition: form-data; name=author Martin -0123456789-- For a file upload, the difference is only that the Content-disposition header will include a file name, and the data can be binary if necessary. When a multipart handler processes a request, it is reading the data from an input stream provided by the container. Typically, for regular query parameters, it will store the value in a hash table. For file parameters, it will store the data in a file and retain information about that file. The Struts implementation uses the FormFile interface to provide access to that information. A multipart implementation could do whatever it wanted to with the data provided from a file upload. Although the Content-disposition header may specify a file name, there is no requirement to store that data as a file. One implementation that would make sense would be to define a size threshold, and store uploaded objects below that size in memory, while writing larger ones to disk. Regarding form beans and binary data, there is no reason why a field in a form bean cannot be a byte array. However, by itself that is not very useful, hence the FormFile interface. If you'll notice, that interface does in fact have a getFileData() method, which will give you the uploaded data as a byte array. In the current implementation, what that actually does is load the contents of the file into memory and hand you back that memory. And there you have binary data in a form field. Hope this helps. -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED
Re: uploading file requires immediate serialization location?
I don't know what would happen. In particular, I don't know what the browser would submit (if anything) in that case. I had thought that the HTML spec stated that the enctype must be multipart/form-data when you use a file input tag, but I just checked, and it (the 4.01 spec) says should, not must. Of course, that doesn't mean that browsers will support it! :-) -- Martin Cooper At 12:55 PM 6/11/01, [EMAIL PROTECTED] wrote: Martin, Hi. Can I pick your brain about an earlier post? I asked what would happen if I have a html:file tag on my form, but without changing the enctype to multipart/form-data? Do you know if I just then get a String containing the filename selected/entered? thanks, Dave Martin Cooper [EMAIL PROTECTED] on 06/11/2001 01:55:07 AM Please respond to [EMAIL PROTECTED] To: [EMAIL PROTECTED], Jonathan Asbell [EMAIL PROTECTED] cc:(bcc: David Hay/Lex/Lexmark) Subject: Re: uploading file requires immediate serialization location? String parameters are not written to a file. Only the bodies of file upload parts are written to disk, and each one to a separate file. The files are written as the input stream (i.e. the request) is processed. Let's say your form has two fields, a textarea called 'myText' and a file input called 'myFile'. After you submit it, and Struts has populated your form bean, you will have: 1) The text from the textarea field is stored in the bean's 'myText' property as a String. 2) The uploaded data is stored in a temporary file somewhere on disk. 3) The 'myFile' property on your bean, which has type FormFile, contains information about the uploaded data (e.g. file name, content type, etc.). The bean is in either request or session scope, as you defined it in your struts-config.xml file. If the bean goes away, then so does the file that holds the uploaded data. Hope this helps. -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Sunday, June 10, 2001 10:48 PM Subject: Re: uploading file requires immediate serialization location? So do you simultaneously write to a file while reading a String parameter when you process a form? What parts of the multipart request do we save in the bean, and in what scope? - Original Message - From: Martin Cooper [EMAIL PROTECTED] To: [EMAIL PROTECTED]; Jonathan Asbell [EMAIL PROTECTED] Sent: Monday, June 11, 2001 1:23 AM Subject: Re: uploading file requires immediate serialization location? Yes, I think you've got it. Just to be clear, though, when you say we need to examine the sections in the header ..., the we here is Struts - you don't need to do anything in your application. Struts makes getParameter() et all work for multipart requests as well as regular requests. What you are seeing in the packages you've looked at is the parsing of a MIME part. The fields in a multipart/form-data request each conform to the specification for a MIME part, and they are separated by a boundary, which is a line containing a pattern defined in a header at the top of the request. Each MIME part consists of a sequence of MIME headers, followed by a blank line, followed by the data for that MIME part, known as the body. A MIME header takes the form header-name: value - for example, Content-type: text/plain. The body is just a bunch of data that conforms to the statements made about it in the headers. Every field in a multipart request is encoded this way. So where a regular query using GET might contain a query string like this: ...author=Martin... a multipart request would represent the same query parameter like this: -0123456789-- Content-disposition: form-data; name=author Martin -0123456789-- For a file upload, the difference is only that the Content-disposition header will include a file name, and the data can be binary if necessary. When a multipart handler processes a request, it is reading the data from an input stream provided by the container. Typically, for regular query parameters, it will store the value in a hash table. For file parameters, it will store the data in a file and retain information about that file. The Struts implementation uses the FormFile interface to provide access to that information. A multipart implementation could do whatever it wanted to with the data provided from a file upload. Although the Content-disposition header may specify a file name, there is no requirement to store that data as a file. One implementation that would make sense would be to define a size threshold, and store uploaded objects below that size in memory, while writing larger ones to disk. Regarding form beans and binary data, there is no reason why a field in a form bean cannot be a byte array. However
RE: uploading file requires immediate serialization location?
Hi, Sorry about not jumping into this conversation, I haven't been around. If you don't specify multipart/form-data, the information is sent as POST data, basically just encoded name/value pairs in your ServletInputStream. So all you're passing is the name of the file that the client specified. -Original Message- From: Martin Cooper [mailto:[EMAIL PROTECTED]] Sent: Monday, June 11, 2001 5:45 PM To: [EMAIL PROTECTED] Subject: Re: uploading file requires immediate serialization location? I don't know what would happen. In particular, I don't know what the browser would submit (if anything) in that case. I had thought that the HTML spec stated that the enctype must be multipart/form-data when you use a file input tag, but I just checked, and it (the 4.01 spec) says should, not must. Of course, that doesn't mean that browsers will support it! :-) -- Martin Cooper At 12:55 PM 6/11/01, [EMAIL PROTECTED] wrote: Martin, Hi. Can I pick your brain about an earlier post? I asked what would happen if I have a html:file tag on my form, but without changing the enctype to multipart/form-data? Do you know if I just then get a String containing the filename selected/entered? thanks, Dave Martin Cooper [EMAIL PROTECTED] on 06/11/2001 01:55:07 AM Please respond to [EMAIL PROTECTED] To: [EMAIL PROTECTED], Jonathan Asbell [EMAIL PROTECTED] cc:(bcc: David Hay/Lex/Lexmark) Subject: Re: uploading file requires immediate serialization location? String parameters are not written to a file. Only the bodies of file upload parts are written to disk, and each one to a separate file. The files are written as the input stream (i.e. the request) is processed. Let's say your form has two fields, a textarea called 'myText' and a file input called 'myFile'. After you submit it, and Struts has populated your form bean, you will have: 1) The text from the textarea field is stored in the bean's 'myText' property as a String. 2) The uploaded data is stored in a temporary file somewhere on disk. 3) The 'myFile' property on your bean, which has type FormFile, contains information about the uploaded data (e.g. file name, content type, etc.). The bean is in either request or session scope, as you defined it in your struts-config.xml file. If the bean goes away, then so does the file that holds the uploaded data. Hope this helps. -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Sunday, June 10, 2001 10:48 PM Subject: Re: uploading file requires immediate serialization location? So do you simultaneously write to a file while reading a String parameter when you process a form? What parts of the multipart request do we save in the bean, and in what scope? - Original Message - From: Martin Cooper [EMAIL PROTECTED] To: [EMAIL PROTECTED]; Jonathan Asbell [EMAIL PROTECTED] Sent: Monday, June 11, 2001 1:23 AM Subject: Re: uploading file requires immediate serialization location? Yes, I think you've got it. Just to be clear, though, when you say we need to examine the sections in the header ..., the we here is Struts - you don't need to do anything in your application. Struts makes getParameter() et all work for multipart requests as well as regular requests. What you are seeing in the packages you've looked at is the parsing of a MIME part. The fields in a multipart/form-data request each conform to the specification for a MIME part, and they are separated by a boundary, which is a line containing a pattern defined in a header at the top of the request. Each MIME part consists of a sequence of MIME headers, followed by a blank line, followed by the data for that MIME part, known as the body. A MIME header takes the form header-name: value - for example, Content-type: text/plain. The body is just a bunch of data that conforms to the statements made about it in the headers. Every field in a multipart request is encoded this way. So where a regular query using GET might contain a query string like this: ...author=Martin... a multipart request would represent the same query parameter like this: -0123456789-- Content-disposition: form-data; name=author Martin -0123456789-- For a file upload, the difference is only that the Content-disposition header will include a file name, and the data can be binary if necessary. When a multipart handler processes a request, it is reading the data from an input stream provided by the container. Typically, for regular query parameters, it will store the value in a hash table. For file parameters, it will store the data in a file and retain information about that file. The Struts implementation uses the FormFile interface to provide access to that information. A multipart implementation
Re: uploading file requires immediate serialization location?
Good question. What you are really asking is what does the html:file tag do?. Struts will generate an input type=file ... tag, where the value of the 'name' attribute is taken from the 'property' attribute of your html:file tag. It will also generate a 'value' attribute. Looking at the source code, it seems that the valueof the 'value' attribute will be the result of calling toString() on the FormFile object. Since that object doesn't override toString(), the result will be nothing useful. On the other hand, browsers usually ignore the 'value' attribute anyway. At this point, the original uploaded file is still on the disk, and will remain there until the form is resubmitted. Then it will be deleted as a part of setting up for parsing the new multipart data. Hope this helps. -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED] To: Martin Cooper [EMAIL PROTECTED] Sent: Sunday, June 10, 2001 5:47 AM Subject: Re: uploading file requires immediate serialization location? Great explanation Martin. Thank you. So what you really have said is that the stream contents gets turned into a FormFile object. Ok. Now the big question. You know when a form is not valid it gets sent beack to the client as strings which pre-populate the form fields. How will this occur in the case of a file input? - Original Message - From: Martin Cooper [EMAIL PROTECTED] To: [EMAIL PROTECTED]; Jonathan Asbell [EMAIL PROTECTED] Sent: Sunday, June 10, 2001 12:20 AM Subject: Re: uploading file requires immediate serialization location? Let me see if I can describe the process. 1. Check to see if the request should be treated as multipart (i.e. content type is multipart/form-data and method is POST). If not, carry on as normal. 2. Find the multipart handler or instantiate one, set it on the form bean, and call it to handle the request. 2a. Iterate over the fields (parts) in the request. 2a1. If the current part is not a file, store it as a String. 2a2. If the current part is a file (according to the Content-Disposition header), create a new file in the temp directory, stream the content of the part to that file, create a new object which implements FormFile, and store the file data in it. 2b. Turn the set of fields into something that looks like regular request parameters. 3. Populate the ActionForm instance from the set of request parameters. Here, the value of a file parameter has type FormFile, so it matches a setter on the form bean that takes a FormFile as a parameter. That's the gist of it, although there are some other nitty gritty details. Almost all of this happens inside the code that populates the form bean from request parameters. It appears (from my reading of the source, anyway) that the temporary files will not be automatically deleted until another request comes in that uses the same form bean instance, or until the form bean instance goes away. Given that, I would recommend calling setMultipartRequestHandler(null) from your form bean's reset() method if you keep your beans in session scope. The part you are interested in, I believe, is 2a2 above. Unfortunately, that code is buried inside an iterator class, so you can't override just that piece. I assume what you would want is that the data is kept in memory instead of to a file. Interestingly, I believe the original implementation did this, but it was changed to use files because of potential memory problems with large uploads. Hope this helps. -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Saturday, June 09, 2001 8:11 PM Subject: Re: uploading file requires immediate serialization location? Hello Martin. So is it POSSIBLE to save binary data in a bean? What does struts do? These are my real questions. If I have a form which besides fields, has an uploaded file, how does the bean actually handle the file? Is there a conceptual step by step you can give me. How does the ActionForm save (and validate) the binary data sent via input type file. - Original Message - From: Martin Cooper [EMAIL PROTECTED] To: [EMAIL PROTECTED]; Jonathan Asbell [EMAIL PROTECTED] Sent: Saturday, June 09, 2001 10:55 PM Subject: Re: uploading file requires immediate serialization location? Internally to Struts, multipart handling is provided through an interface, MultipartRequestHandler. In Struts 1.0, the only supplied implementation of this interface is DiskMultipartRequestHandler, which, as you might expect, writes file parts to disk as it encounters them. Struts does allow you to configure the multipart handler to use, by specifying the class name in the multipartClass init-param for your web app. This allows you to provide your own implementation if you want
Re: uploading file requires immediate serialization location?
Martin, you seem to understand this subject well, so let me take a shot and tell me if I am correct: A multi-part request is a request, but a different one. That is, with a regular request things have been abstracted for us nicely with getParameter etc., but a request submitted as multipart is not handled nicely for us by the servlet spec and is a whole different animal. This type of request needs to be handled uniquely (though I dont understand why the servlet spec does not have standard abstractions for it), because it may contain binary non-text content accompanied by regular content. In such a request we need to examine the sections in the header and parse for certain values we are expecting to separate out the regular text values submitted from the binary parts, and then handle the binary parts. Things I still dont get: In all packages I have examined that handle multipart requests, there is always a notion of looking for the line : , then looking for the blank line after that, and then reading in binary values that follow the blank line up until the boundry which is a String in a known format (see link below). What I dont understand is what are our options in handling this binary stuff which is not text. Most packages I have seen write it to a file. I'm not sure if there is a way to save a binary object at all, let alone save it in a filed value in a bean. How do you store a binary object in a field? == REFERENCE == For those interested see this article: www.onjava.com/lpt/a//onjava/2001/04/05/upload.html Available servlet packages http://www.servlets.com/cos/index.html - Original Message - From: Martin Cooper [EMAIL PROTECTED] To: Jonathan Asbell [EMAIL PROTECTED] Cc: [EMAIL PROTECTED] Sent: Sunday, June 10, 2001 3:01 PM Subject: Re: uploading file requires immediate serialization location? Good question. What you are really asking is what does the html:file tag do?. Struts will generate an input type=file ... tag, where the value of the 'name' attribute is taken from the 'property' attribute of your html:file tag. It will also generate a 'value' attribute. Looking at the source code, it seems that the valueof the 'value' attribute will be the result of calling toString() on the FormFile object. Since that object doesn't override toString(), the result will be nothing useful. On the other hand, browsers usually ignore the 'value' attribute anyway. At this point, the original uploaded file is still on the disk, and will remain there until the form is resubmitted. Then it will be deleted as a part of setting up for parsing the new multipart data. Hope this helps. -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED] To: Martin Cooper [EMAIL PROTECTED] Sent: Sunday, June 10, 2001 5:47 AM Subject: Re: uploading file requires immediate serialization location? Great explanation Martin. Thank you. So what you really have said is that the stream contents gets turned into a FormFile object. Ok. Now the big question. You know when a form is not valid it gets sent beack to the client as strings which pre-populate the form fields. How will this occur in the case of a file input? - Original Message - From: Martin Cooper [EMAIL PROTECTED] To: [EMAIL PROTECTED]; Jonathan Asbell [EMAIL PROTECTED] Sent: Sunday, June 10, 2001 12:20 AM Subject: Re: uploading file requires immediate serialization location? Let me see if I can describe the process. 1. Check to see if the request should be treated as multipart (i.e. content type is multipart/form-data and method is POST). If not, carry on as normal. 2. Find the multipart handler or instantiate one, set it on the form bean, and call it to handle the request. 2a. Iterate over the fields (parts) in the request. 2a1. If the current part is not a file, store it as a String. 2a2. If the current part is a file (according to the Content-Disposition header), create a new file in the temp directory, stream the content of the part to that file, create a new object which implements FormFile, and store the file data in it. 2b. Turn the set of fields into something that looks like regular request parameters. 3. Populate the ActionForm instance from the set of request parameters. Here, the value of a file parameter has type FormFile, so it matches a setter on the form bean that takes a FormFile as a parameter. That's the gist of it, although there are some other nitty gritty details. Almost all of this happens inside the code that populates the form bean from request parameters. It appears (from my reading of the source, anyway) that the temporary files will not be automatically deleted until another request comes in that uses the same form bean instance, or until the form bean instance goes away. Given that, I would recommend calling
Re: uploading file requires immediate serialization location?
So do you simultaneously write to a file while reading a String parameter when you process a form? What parts of the multipart request do we save in the bean, and in what scope? - Original Message - From: Martin Cooper [EMAIL PROTECTED] To: [EMAIL PROTECTED]; Jonathan Asbell [EMAIL PROTECTED] Sent: Monday, June 11, 2001 1:23 AM Subject: Re: uploading file requires immediate serialization location? Yes, I think you've got it. Just to be clear, though, when you say we need to examine the sections in the header ..., the we here is Struts - you don't need to do anything in your application. Struts makes getParameter() et all work for multipart requests as well as regular requests. What you are seeing in the packages you've looked at is the parsing of a MIME part. The fields in a multipart/form-data request each conform to the specification for a MIME part, and they are separated by a boundary, which is a line containing a pattern defined in a header at the top of the request. Each MIME part consists of a sequence of MIME headers, followed by a blank line, followed by the data for that MIME part, known as the body. A MIME header takes the form header-name: value - for example, Content-type: text/plain. The body is just a bunch of data that conforms to the statements made about it in the headers. Every field in a multipart request is encoded this way. So where a regular query using GET might contain a query string like this: ...author=Martin... a multipart request would represent the same query parameter like this: -0123456789-- Content-disposition: form-data; name=author Martin -0123456789-- For a file upload, the difference is only that the Content-disposition header will include a file name, and the data can be binary if necessary. When a multipart handler processes a request, it is reading the data from an input stream provided by the container. Typically, for regular query parameters, it will store the value in a hash table. For file parameters, it will store the data in a file and retain information about that file. The Struts implementation uses the FormFile interface to provide access to that information. A multipart implementation could do whatever it wanted to with the data provided from a file upload. Although the Content-disposition header may specify a file name, there is no requirement to store that data as a file. One implementation that would make sense would be to define a size threshold, and store uploaded objects below that size in memory, while writing larger ones to disk. Regarding form beans and binary data, there is no reason why a field in a form bean cannot be a byte array. However, by itself that is not very useful, hence the FormFile interface. If you'll notice, that interface does in fact have a getFileData() method, which will give you the uploaded data as a byte array. In the current implementation, what that actually does is load the contents of the file into memory and hand you back that memory. And there you have binary data in a form field. Hope this helps. -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Sunday, June 10, 2001 1:19 PM Subject: Re: uploading file requires immediate serialization location? Martin, you seem to understand this subject well, so let me take a shot and tell me if I am correct: A multi-part request is a request, but a different one. That is, with a regular request things have been abstracted for us nicely with getParameter etc., but a request submitted as multipart is not handled nicely for us by the servlet spec and is a whole different animal. This type of request needs to be handled uniquely (though I dont understand why the servlet spec does not have standard abstractions for it), because it may contain binary non-text content accompanied by regular content. In such a request we need to examine the sections in the header and parse for certain values we are expecting to separate out the regular text values submitted from the binary parts, and then handle the binary parts. Things I still dont get: In all packages I have examined that handle multipart requests, there is always a notion of looking for the line : , then looking for the blank line after that, and then reading in binary values that follow the blank line up until the boundry which is a String in a known format (see link below). What I dont understand is what are our options in handling this binary stuff which is not text. Most packages I have seen write it to a file. I'm not sure if there is a way to save a binary object at all, let alone save it in a filed value in a bean. How do you store a binary object in a field? == REFERENCE == For those interested see this article: www.onjava.com/lpt
Re: uploading file requires immediate serialization location?
String parameters are not written to a file. Only the bodies of file upload parts are written to disk, and each one to a separate file. The files are written as the input stream (i.e. the request) is processed. Let's say your form has two fields, a textarea called 'myText' and a file input called 'myFile'. After you submit it, and Struts has populated your form bean, you will have: 1) The text from the textarea field is stored in the bean's 'myText' property as a String. 2) The uploaded data is stored in a temporary file somewhere on disk. 3) The 'myFile' property on your bean, which has type FormFile, contains information about the uploaded data (e.g. file name, content type, etc.). The bean is in either request or session scope, as you defined it in your struts-config.xml file. If the bean goes away, then so does the file that holds the uploaded data. Hope this helps. -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Sunday, June 10, 2001 10:48 PM Subject: Re: uploading file requires immediate serialization location? So do you simultaneously write to a file while reading a String parameter when you process a form? What parts of the multipart request do we save in the bean, and in what scope? - Original Message - From: Martin Cooper [EMAIL PROTECTED] To: [EMAIL PROTECTED]; Jonathan Asbell [EMAIL PROTECTED] Sent: Monday, June 11, 2001 1:23 AM Subject: Re: uploading file requires immediate serialization location? Yes, I think you've got it. Just to be clear, though, when you say we need to examine the sections in the header ..., the we here is Struts - you don't need to do anything in your application. Struts makes getParameter() et all work for multipart requests as well as regular requests. What you are seeing in the packages you've looked at is the parsing of a MIME part. The fields in a multipart/form-data request each conform to the specification for a MIME part, and they are separated by a boundary, which is a line containing a pattern defined in a header at the top of the request. Each MIME part consists of a sequence of MIME headers, followed by a blank line, followed by the data for that MIME part, known as the body. A MIME header takes the form header-name: value - for example, Content-type: text/plain. The body is just a bunch of data that conforms to the statements made about it in the headers. Every field in a multipart request is encoded this way. So where a regular query using GET might contain a query string like this: ...author=Martin... a multipart request would represent the same query parameter like this: -0123456789-- Content-disposition: form-data; name=author Martin -0123456789-- For a file upload, the difference is only that the Content-disposition header will include a file name, and the data can be binary if necessary. When a multipart handler processes a request, it is reading the data from an input stream provided by the container. Typically, for regular query parameters, it will store the value in a hash table. For file parameters, it will store the data in a file and retain information about that file. The Struts implementation uses the FormFile interface to provide access to that information. A multipart implementation could do whatever it wanted to with the data provided from a file upload. Although the Content-disposition header may specify a file name, there is no requirement to store that data as a file. One implementation that would make sense would be to define a size threshold, and store uploaded objects below that size in memory, while writing larger ones to disk. Regarding form beans and binary data, there is no reason why a field in a form bean cannot be a byte array. However, by itself that is not very useful, hence the FormFile interface. If you'll notice, that interface does in fact have a getFileData() method, which will give you the uploaded data as a byte array. In the current implementation, what that actually does is load the contents of the file into memory and hand you back that memory. And there you have binary data in a form field. Hope this helps. -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Sunday, June 10, 2001 1:19 PM Subject: Re: uploading file requires immediate serialization location? Martin, you seem to understand this subject well, so let me take a shot and tell me if I am correct: A multi-part request is a request, but a different one. That is, with a regular request things have been abstracted for us nicely with getParameter etc., but a request submitted as multipart is not handled nicely for us by the servlet spec and is a whole different animal. This type
Re: uploading file requires immediate serialization location?
You wrote... The uploaded data is stored in a temporary file somewhere on disk.The bean is in either request or session scope. If the bean goes away, then so does the file that holds the uploaded data. I thought you said the file was written to disk? Thus the binary is not in the bean. Or is it that the FormFile has all this data and IT is in the bean. So I end up with a file on disk that is in a state of not be associated with anything yet, and whos filename and input field names I have lost when the bean went away. Is that it? If we are keeping the FormFile in the bean, in the session and the FormFile indeed does contain the binary, than this is a bad thing. We should at theleast kill the binary from the FormFile object so we CAN safely put it in the session. (Dont know if I mentioned by weblogic croaks/freaks if the session has too much k in it. - Original Message - From: Martin Cooper [EMAIL PROTECTED] To: [EMAIL PROTECTED]; Jonathan Asbell [EMAIL PROTECTED] Sent: Monday, June 11, 2001 1:55 AM Subject: Re: uploading file requires immediate serialization location? String parameters are not written to a file. Only the bodies of file upload parts are written to disk, and each one to a separate file. The files are written as the input stream (i.e. the request) is processed. Let's say your form has two fields, a textarea called 'myText' and a file input called 'myFile'. After you submit it, and Struts has populated your form bean, you will have: 1) The text from the textarea field is stored in the bean's 'myText' property as a String. 2) The uploaded data is stored in a temporary file somewhere on disk. 3) The 'myFile' property on your bean, which has type FormFile, contains information about the uploaded data (e.g. file name, content type, etc.). The bean is in either request or session scope, as you defined it in your struts-config.xml file. If the bean goes away, then so does the file that holds the uploaded data. Hope this helps. -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Sunday, June 10, 2001 10:48 PM Subject: Re: uploading file requires immediate serialization location? So do you simultaneously write to a file while reading a String parameter when you process a form? What parts of the multipart request do we save in the bean, and in what scope? - Original Message - From: Martin Cooper [EMAIL PROTECTED] To: [EMAIL PROTECTED]; Jonathan Asbell [EMAIL PROTECTED] Sent: Monday, June 11, 2001 1:23 AM Subject: Re: uploading file requires immediate serialization location? Yes, I think you've got it. Just to be clear, though, when you say we need to examine the sections in the header ..., the we here is Struts - you don't need to do anything in your application. Struts makes getParameter() et all work for multipart requests as well as regular requests. What you are seeing in the packages you've looked at is the parsing of a MIME part. The fields in a multipart/form-data request each conform to the specification for a MIME part, and they are separated by a boundary, which is a line containing a pattern defined in a header at the top of the request. Each MIME part consists of a sequence of MIME headers, followed by a blank line, followed by the data for that MIME part, known as the body. A MIME header takes the form header-name: value - for example, Content-type: text/plain. The body is just a bunch of data that conforms to the statements made about it in the headers. Every field in a multipart request is encoded this way. So where a regular query using GET might contain a query string like this: ...author=Martin... a multipart request would represent the same query parameter like this: -0123456789-- Content-disposition: form-data; name=author Martin -0123456789-- For a file upload, the difference is only that the Content-disposition header will include a file name, and the data can be binary if necessary. When a multipart handler processes a request, it is reading the data from an input stream provided by the container. Typically, for regular query parameters, it will store the value in a hash table. For file parameters, it will store the data in a file and retain information about that file. The Struts implementation uses the FormFile interface to provide access to that information. A multipart implementation could do whatever it wanted to with the data provided from a file upload. Although the Content-disposition header may specify a file name, there is no requirement to store that data as a file. One implementation that would make sense would be to define a size threshold, and store uploaded objects below that size in memory, while writing
Re: uploading file requires immediate serialization location?
Internally to Struts, multipart handling is provided through an interface, MultipartRequestHandler. In Struts 1.0, the only supplied implementation of this interface is DiskMultipartRequestHandler, which, as you might expect, writes file parts to disk as it encounters them. Struts does allow you to configure the multipart handler to use, by specifying the class name in the multipartClass init-param for your web app. This allows you to provide your own implementation if you want to (although this is no small task). -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Saturday, June 09, 2001 6:39 AM Subject: uploading file requires immediate serialization location? Hello all. I am just trying to understand an aspect of a multipart request. When you submit after using an input of type file, do you have to provide an immediate location for the file to be serialized to, or can you store it in a java object (in a bean's field) as a binary object until you are ready to serialize it. The reason is that I want to hold a jpeg in a bean until the person completes the last page of the form, and THEN serialize it.
Re: uploading file requires immediate serialization location?
Hello Martin. So is it POSSIBLE to save binary data in a bean? What does struts do? These are my real questions. If I have a form which besides fields, has an uploaded file, how does the bean actually handle the file? Is there a conceptual step by step you can give me. How does the ActionForm save (and validate) the binary data sent via input type file. - Original Message - From: Martin Cooper [EMAIL PROTECTED] To: [EMAIL PROTECTED]; Jonathan Asbell [EMAIL PROTECTED] Sent: Saturday, June 09, 2001 10:55 PM Subject: Re: uploading file requires immediate serialization location? Internally to Struts, multipart handling is provided through an interface, MultipartRequestHandler. In Struts 1.0, the only supplied implementation of this interface is DiskMultipartRequestHandler, which, as you might expect, writes file parts to disk as it encounters them. Struts does allow you to configure the multipart handler to use, by specifying the class name in the multipartClass init-param for your web app. This allows you to provide your own implementation if you want to (although this is no small task). -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Saturday, June 09, 2001 6:39 AM Subject: uploading file requires immediate serialization location? Hello all. I am just trying to understand an aspect of a multipart request. When you submit after using an input of type file, do you have to provide an immediate location for the file to be serialized to, or can you store it in a java object (in a bean's field) as a binary object until you are ready to serialize it. The reason is that I want to hold a jpeg in a bean until the person completes the last page of the form, and THEN serialize it.
Re: uploading file requires immediate serialization location?
Let me see if I can describe the process. 1. Check to see if the request should be treated as multipart (i.e. content type is multipart/form-data and method is POST). If not, carry on as normal. 2. Find the multipart handler or instantiate one, set it on the form bean, and call it to handle the request. 2a. Iterate over the fields (parts) in the request. 2a1. If the current part is not a file, store it as a String. 2a2. If the current part is a file (according to the Content-Disposition header), create a new file in the temp directory, stream the content of the part to that file, create a new object which implements FormFile, and store the file data in it. 2b. Turn the set of fields into something that looks like regular request parameters. 3. Populate the ActionForm instance from the set of request parameters. Here, the value of a file parameter has type FormFile, so it matches a setter on the form bean that takes a FormFile as a parameter. That's the gist of it, although there are some other nitty gritty details. Almost all of this happens inside the code that populates the form bean from request parameters. It appears (from my reading of the source, anyway) that the temporary files will not be automatically deleted until another request comes in that uses the same form bean instance, or until the form bean instance goes away. Given that, I would recommend calling setMultipartRequestHandler(null) from your form bean's reset() method if you keep your beans in session scope. The part you are interested in, I believe, is 2a2 above. Unfortunately, that code is buried inside an iterator class, so you can't override just that piece. I assume what you would want is that the data is kept in memory instead of to a file. Interestingly, I believe the original implementation did this, but it was changed to use files because of potential memory problems with large uploads. Hope this helps. -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Saturday, June 09, 2001 8:11 PM Subject: Re: uploading file requires immediate serialization location? Hello Martin. So is it POSSIBLE to save binary data in a bean? What does struts do? These are my real questions. If I have a form which besides fields, has an uploaded file, how does the bean actually handle the file? Is there a conceptual step by step you can give me. How does the ActionForm save (and validate) the binary data sent via input type file. - Original Message - From: Martin Cooper [EMAIL PROTECTED] To: [EMAIL PROTECTED]; Jonathan Asbell [EMAIL PROTECTED] Sent: Saturday, June 09, 2001 10:55 PM Subject: Re: uploading file requires immediate serialization location? Internally to Struts, multipart handling is provided through an interface, MultipartRequestHandler. In Struts 1.0, the only supplied implementation of this interface is DiskMultipartRequestHandler, which, as you might expect, writes file parts to disk as it encounters them. Struts does allow you to configure the multipart handler to use, by specifying the class name in the multipartClass init-param for your web app. This allows you to provide your own implementation if you want to (although this is no small task). -- Martin Cooper - Original Message - From: Jonathan Asbell [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Saturday, June 09, 2001 6:39 AM Subject: uploading file requires immediate serialization location? Hello all. I am just trying to understand an aspect of a multipart request. When you submit after using an input of type file, do you have to provide an immediate location for the file to be serialized to, or can you store it in a java object (in a bean's field) as a binary object until you are ready to serialize it. The reason is that I want to hold a jpeg in a bean until the person completes the last page of the form, and THEN serialize it.