Hi, To get a bigger picture let me explain what I would like to actually craft :
In a multipart POST request, I'd like to have form params and a file attachement (like the example above). And I would like to handle myself the inputstream of the file. In order do stuff like - checking some headers, for example Content-Length on one of the Attachement, Content-Disposition etc - consuming the content of the given inputstream of this part to store it in a temporary file However in the MessageBodyReader, the entityStream looks like it's been closed and already consumed. Debugging reveals that an AttatchmentDeserializer already consumed the stream, and created an Attachement collection, however my provider wasn't called at that time. If the opportunity is available I would like to copy these bytes to another outputstream. Is it possible or should I use attachments ? I'd like as much as possible avoid technical code in the resource, and have a reference to a TemporaryBinaryFile. Here's my comment on Content-Disposition : On Mon, Nov 5, 2012 at 11:17 PM, Sergey Beryozkin <[email protected]>wrote: > Hi > > > On 05/11/12 19:27, Brice Dutheil wrote: > >> Hi, >> >> I'm crafting a resource that should accept multipart POST request. >> >> Here's the method : >> >> ==============================**================== >> @POST >> @Produces({MediaType.**APPLICATION_JSON}) >> @Consumes(MediaType.MULTIPART_**FORM_DATA) >> public MetaData archive(@FormParam("title") String title, >> @FormParam("revision") String revision, >> @Multipart("archive") >> TemporaryBinaryFile >> temporaryBinaryFile) { >> ==============================**================== >> >> Also I tried with @Multipart instead of @FormParam >> >> ==============================**================== >> @POST >> @Produces({MediaType.**APPLICATION_JSON}) >> @Consumes(MediaType.MULTIPART_**FORM_DATA) >> public DocumentMetaData archive(@Multipart(value = "title", required = >> false) @FormParam("title") String title, >> @Multipart(value = "revision", >> required = >> false) String revision, >> @Multipart("archive") >> TemporaryBinaryFile >> temporaryBinaryFile) { >> > > You have @FormParam and @Multipart attached to 'title', drop @FormParam, I > think it only works because 'title' is a simple parameter. > > Yes I wrongly copied/ modified the code in the mail, however I tested both setup separately. Anyway, as you advised me I will inly use Multipart now. > > ==============================**================== >> >> And here is the raw request : >> ==============================**================== >> Address: >> http://localhost:8080/api/v1.**0/document/archive<http://localhost:8080/api/v1.0/document/archive> >> Encoding: ISO-8859-1 >> Http-Method: POST >> Content-Type: multipart/form-data;boundary=**partie >> Headers: {Accept=[*/*], accept-charset=[ISO-8859-1,** >> utf-8;q=0.7,*;q=0.3], >> accept-encoding=[gzip,deflate,**sdch], Content-Length=[301], >> content-type=[multipart/form-**data;boundary=partie]} >> Payload: >> --partie >> Content-Disposition: form-data; name="title" >> Content-ID: title >> >> the.title >> --partie >> Content-Disposition: form-data; name="revision" >> Content-ID: revision >> >> some.revision >> --partie >> Content-Disposition: form-data; name="archive"; filename="file.txt" >> Content-Type: text/plain >> >> I've got a woman, way over town... >> --partie >> ==============================**================== >> >> However the title and revision values are incorrect because they are ended >> by a new line char '\n'. Hence these parameters are not validated by my >> validator (which is using Message.getContent), >> >> I don't think this is a normal behavior, but I might be wrong, maybe about >> the specs, or my request. Note that I had to add the Content-ID when using >> the Multipart annotation. >> > > What CXF version is it ? Content-Disposition 'name' is definitely checked > too. > > Also I found part of the code that should check the Content-Disposition, however I have found that the first letter 'C' disappeared and the key in the attachment header is now 'ontent-Disposition' which can complicate things further, and probably explains why, I needed a Content-ID header in each part. Although the first part got his header Content-Disposition always correctly decoded. Adding another new line after the boundary fixes looks like a workaround though, but i'd rather not impose this on the API users :/ I couldn't figure out yet where the code could is consuming the additional char. I just know that at some point, the LazyAttachmentCollection has the remaining attachment (AttachmentImpl), and the first header is wrong. About Content-Disposition name, it is checked only if there is no Content-ID, however it seems at some point the default Content-ID is added " [email protected]", which defeats the purpose of the following code. private static boolean matchAttachmentId(Attachment at, Multipart mid, MediaType multipartType) { if (at.getContentId().equals(mid.value())) { return true; } ContentDisposition cd = at.getContentDisposition(); if (cd != null && mid.value().equals(cd.getParameter("name"))) { return true; } return false; } I have tested these behavior on CXF 2.6.3 and 2.7.0, I'm using JDK 7 also. > > Maybe there is something I should do ? >> >> >> I have a workaround for that, I've made an interceptor whose role is to >> trim strings. But I find it rather inelegant to do that. >> >> Or am I missing something ? >> >> > I don't have the immediate answer to it, we have few tests were simple > parts are transmitted and no new line/return characters make it into the > representation. > > Can you please experiment with Content-Transfer-Encoding header ? > Nope, no change in behavior, although I only used the 8bit value, as my shooter only uses ascii chars. Cheers, -- Brice
