Java ProxyServlet destroys filename encoding - java

I am using a Java Proxy Servlet that forwards any http request to a server based using Apache httpClient. It works nice, but filenames, that using special characters like "öÖäÄüÜß" get corrupted.
Browser sends
Content-Disposition: form-data; name="file"; filename="lp_fos_fr-ööÖÖääÄÄüüÜÜß_technik.pdf"
Content-Type: application/pdf
After forwarding the request by ServletProxy
HttpEntityEnclosingRequest eProxyRequest =
new BasicHttpEntityEnclosingRequest(method, proxyRequestUri);
eProxyRequest.setEntity(new InputStreamEntity(servletRequest.getInputStream(), servletRequest.getContentLength()));
The filename is corrupted:
Content-Disposition: form-data; name="file"; filename="lp_fos_fr-.........................._technik.pdf"
Content-Type: application/pdf
What could I do to preserve the filename?

Related

How to fix different multipart boundary implementations?

I created a file upload functionality in Jersey.
#POST
#Path("/import")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public static Response importFile(
#FormDataParam("file") InputStream fileInputStream,
#FormDataParam("file") FormDataContentDisposition fileMetaData,
When I send a file as multipart formdata from the browser (Firefox and Chrome) using Fetch API or a jQuery POST, Jersey responds with a org.jvnet.mimepull.MIMEParsingException: Missing start boundary.
This is apparently not due to the fact that e.g. Chrome uses a case-sensitive boundary, as others have had, since the issue happens in Firefox as well, which uses a numeric boundary.
It seems that in my case, the browser sends the boundary with two additional dashes before each boundary in the body and after the last one (which seems to be correct according to the multipart specification https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html), but Jersey (2.25.1) / Mimepull (1.9.14) does not accept that.
Content-Type multipart/form-data; boundary=
---------------------------23978830417520517351040096390
-----------------------------23978830417520517351040096390
Content-Disposition: form-data; name="file"; filename="testdata.csv"
Content-Type: text/csv
<snip>
-----------------------------23978830417520517351040096390--
On the contrary, when I send my request using Postman, it encodes the boundary in the body without those two additional dashes and Jersey accepts the request.
POST /myapi/import HTTP/1.1
Content-Length: 708
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="testdata.csv"
Content-Type: text/csv
(data)
----WebKitFormBoundary7MA4YWxkTrZu0gW
<snip>
----WebKitFormBoundary7MA4YWxkTrZu0gW
What is the correct behaviour in this case and how is it possible to implement the file upload in a way that different clients can use it?
Is there an alternative to using multipart implementation for file uploads?

Uploading JSON string besides File with Ionic native file-transfer plugin to Java JAX-RS Server

I am trying to upload a file to my Java JAX-RS(Jersey) web service.
My method signature on the server side if anyone interested is like this;
upload(#FormDataParam("file") InputStream uploadedStream, #FormDataParam("file") FormDataContentDisposition fileDetail, #FormDataParam("question") String req_question, #Context HttpHeaders headers)
When I try to upload a file with Postman (Client for testing) using multipart/form-data, it is working properly. When I sniff it with Fiddler I see this;
POST http://localhost:8080/application/question/post HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryT79BovKwL6ObBceu
Accept-Language: tr-TR,tr;q=0.8,en-US;q=0.6,en;q=0.4
------WebKitFormBoundaryT79BovKwL6ObBceu
Content-Disposition: form-data; name="file"; filename="PARS.png"
Content-Type: image/png
[HERE SOME STRANGE RAW BINARY DATA]
------WebKitFormBoundaryT79BovKwL6ObBceu
Content-Disposition: form-data; name="question"
{"title": "This is title!", "fk_field_id":1}
------WebKitFormBoundaryT79BovKwL6ObBceu--
As you can see it has proper differentation of types of data being sent. But when I try to achieve the same upload with Ionic/Angular my request look like this;
POST http://localhost:8080/application/question/post HTTP/1.1
Content-Type: multipart/form-data
Accept-Language: tr-TR,tr;q=0.8,en-US;q=0.6,en;q=0.4
/Exif II* [SOME STRANGE RAW BINARY DATA]
I only see binary, there is no differentiation nor sign of the params I sent. Here is my Angular code that is responded as failed.
let options: FileUploadOptions =
{
fileKey: 'file',
headers: headers,
params: {"title": "This is title!", "fk_field_id":1} // Actually I am getting this as method parameter yet to shorten code I moved it here
};
path = {MY ENDPOINT IN SERVER}
filePath = file:///storage/emulated/0/Android/data/io.ionic.starter/cache/1497313256081.jpg // Getting as method param
fileTransfer.upload(filePath, path, options).then(things => {
//Some console.log
});

MTOM Message parsing

I am getting the below response from a WCF service
--uuid:57cad2b9-196b-4780-9643-cab6131bed98+id=43
Content-ID: <http://tempuri.org/0>
Content-Transfer-Encoding: 8bit
Content-Type: application/xop+xml;charset=utf-8;type="text/xml"
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><DownloadFileResponse xmlns="http://tempuri.org/"><DownloadFileResult xmlns:a="http://schemas.datacontract.org/2004/07/OneC_GenericUploadMessageContract" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><a:EncryptedFileUploadID i:nil="true"/><a:FileContentId i:nil="true"/><a:FileException i:nil="true"/><a:FileExternalURL i:nil="true"/><a:FileLocation i:nil="true"/><a:FileName>176827.jpeg</a:FileName><a:FileURL>C9533C2F-AC59-E411-9405-005056853C65\_00000000-0000-0000-0000-000000000000_56_9_2016_15_11_4_13_636010818640138255.jpeg</a:FileURL><a:FileUploadId>0</a:FileUploadId><a:Filestatus i:nil="true"/><a:OutgoingFile><xop:Include href="cid:http://tempuri.org/1/636029758108722711" xmlns:xop="http://www.w3.org/2004/08/xop/include"/></a:OutgoingFile></DownloadFileResult></DownloadFileResponse></s:Body></s:Envelope>
--uuid:57cad2b9-196b-4780-9643-cab6131bed98+id=43
Content-ID: <http://tempuri.org/1/636029758108722711>
Content-Transfer-Encoding: binary
Content-Type: application/octet-stream
-----binary content here----
i tried parsing this using How to parse XOP/MTOM SOAP response using java?
I am getting boundary missing exception. I am not seeing any boundary specified for this response.
Am i missing something or is this message not properly send?

MultipartEntityBuilder: Omit Content-Type and Content-Transfer

I'm trying to mimic my Browsers behaviour on a multipart/form-data POST request using org.apache.http.entity.mime.MultipartEntityBuilder
My browser only sends Content-Disposition, but no Content-Type or Content-Transfer-Encoding Headers.
I tried to use MultipartEntityBuilder.addPart() and addTextBody() but both add those Headers by default:
What I want (what my chrome browser does):
POST .../some.jsp HTTP/1.1
Host: ...
Connection: keep-alive
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary6tcnkxC7txvqE5Xl
------WebKitFormBoundary6tcnkxC7txvqE5Xl
Content-Disposition: form-data; name="merkmal"
5
What I get from MultipartEntityBuilder
POST.../some.jsp HTTP/1.1
Host: ...
Content-Type: multipart/form-data; boundary=m9Zb2QD-QaH-j-HqgGQfI8KwDkToz17ULYkZ
--m9Zb2QD-QaH-j-HqgGQfI8KwDkToz17ULYkZ
Content-Disposition: form-data; name="merkmal"
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
5
Why?: The designated server thinks that everything after name="merkmal" is the value of merkmal (including the Headers). Other possible reason: Could the whole request somehow have a wrong encoding (especially for newline) ?
alright - intense googeling finally produced an answer.
1) There are apparently some servers that do not get on well with the "Content-Transfer-Encoding" header.
2) There is a browser compatibility mode in HttpComponents that is used like this:
MultipartEntityBuilder uploadEntityBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
Using the compatibility code, both unwanted headers (Content-Transfer-Encoding and Content-Type) are not used any longer!
I hope this will some day help some poor sod like me ;)

How should I parse a POST request message's content in a Tomcat servlet

I am trying to develop a Java servlet in Tomcat to handle post requests, eventually intending to process files and return said processed files in the response to the client. Based on my searching so far, it seems that the requests I'm going to be handling are given an unusual format. I can suggest alternatives, but I do not have control over the design of the request, which will look as follows:
POST /api/0/actions/image HTTP/1.1
Host: <host>.com
Content-Length: <content-length>
Content-Type: multipart/form-data; boundary=<boundary>
Accept-Encoding: gzip, deflate, compress
Accept: */*
User-Agent: <user-agent>
--<boundary>
Content-Disposition: form-data; name="application"
{<authentication_info_as_JSON_object>}
--<boundary>
Content-Disposition: form-data; name="inputName"
<inputname>
--<boundary>
Content-Disposition: form-data; name="options"
{<options_as_JSON}
--<boundary>
Content-Disposition: form-data; name="input"; filename="<inputname>"
Content-Type: <content-type>
<file-binary>
--<boundary>--
I could parse this request's content as text using regular expressions and standard string processing methods, reconstructing the JSON objects and file(s) I need to handle manually. But that strikes me as a bug-prone and difficult to maintain approach. Are there open source tools out there that can help me process this request in a more structured or standard way?
Thanks in advance.
How is this unusual?
Use Apache Commons' FileUpload or equivalent.
If you're on a Servlet 3.0 container, this is baked in, e.g., HttpServletRequest.getParts()

Categories

Resources