Processing Multi-form data in Netty - java

With a client like this
StringBody body = new StringBody("form_username", Charset.forName("UTF-8"));
multipart.addPart("username", body);
ByteArrayBody bBody = new ByteArrayBody(bs, "form_command.dat");
multipart.addPart("data", bBody);
httppost.setEntity(multipart);
How are the values supposed to be retrieved in the netty server. I already have a HttpRequestDecoder added to the pipeline. And the messageReceived handled thus
HttpRequest request = (HttpRequest) e.getMessage();
this.mRequest = request;
if (is100ContinueExpected(request)) {
send100Continue(e);
}
ChannelBuffer content = request.getContent();
if (content.readable()) {
System.out.println("Content()\n" + content.toString(CharsetUtil.UTF_8) + "\r\n");
}
Print outputs .
Content()
--Xdq2t6unVsUp191MKhpR6BXz5P7Eoo
Content-Disposition: form-data; name="username"
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
form_username
--Xdq2t6unVsUp191MKhpR6BXz5P7Eoo
Content-Disposition: form-data; name="data"; filename="form_command.dat"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
--Xdq2t6unVsUp191MKhpR6BXz5P7Eoo--
End of contents

You need to use the new HttpPostRequestDecoder. This is only available in the upcoming Netty 3.5 (3 branch) and Netty 4 (master branch).
Here an example usage.
If you need to use it now, you can just copy the files mentioned in this pull request into your project namespace and use it.
Hope this helps.

Related

How set custom 'Content-Disposition' Header in POST request in Java?

The server I am sending a POST request to requires extra parameters in the Content-Disposition field that are easily added in C# code, but I am struggling to replicate this functionality in Java.
The working C# code:
using (var content = new MultipartFormDataContent()) {
var fileContent = new ByteArrayContent(System.IO.File.ReadAllBytes("filepath"));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "file",
FileName = "file.zip.encrypted",
};
fileContent.Headers.ContentDisposition.Parameters.Add(new NameValueHeaderValue("Type", "CSV"));
fileContent.Headers.ContentDisposition.Parameters.Add(new NameValueHeaderValue("Token", jwt));
content.Add(fileContent);
var requestUri = "url";
var result = client.PostAsync(requestUri, content).Result;
When I print the above request headers the Content-Disposition header looks like:
Content-Disposition: form-data; name=file; filename=file.zip.encrypted; Type=CSV; Token=jwt
Attempting to replicate this POST request in Java Apache Http:
File file = new File("filepath");
String headerValue = "form-data; name=file; filename=\"file.zip.encrypted\"; Type=\"CSV\"; Token=\""+jwtToken+"\"";
try (CloseableHttpClient client2 = HttpClients.createDefault()) {
HttpPost post2 = new HttpPost(url);
HttpEntity entity = MultipartEntityBuilder.create().addPart("file", new FileBody(file)).build();
post2.setHeader("Content-Disposition", headerValue);
post2.setEntity(entity);
try (CloseableHttpResponse response2 = client2.execute(post2)) {
System.out.println(response2.toString());
}
}
However, when I print the Headers in this request, only the name and filename fields are captured, and not the other parameters required in the Content-Disposition header. This is leading to Internal Server Error responses, as the Header does not contain the required parameters. (tried with and without the added quotes around field values)
Content-Disposition: form-data; name="file"; filename="file.zip.encrypted"
Any help getting the C# POST request behavior replicated in Java would be greatly appreciated, thanks!

OkHttp3 response string show html file instaed of download file data

I using Okhttp3 for download file from server in android application. my link is http://www.webweb.infinityfreeapp.com/lichi/download.php?path=Add.jpg it download file in firefox, chorme smoothly, while in okhttp3 response string shows
<html><body><script>document.cookie="_test=9e105a99e90025d241c180c29fad3231 ; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/" ;document.location.href="http://www.webweb.infinityfreeapp.com/lichi/download.php?path=Add.jpg&i=1";</script></body></html>
but i feel response string has Add.jpg file data. so, what can i change in okhttp3 code or php code that i gather App.jpg data in response string of okhttp3
Php Code
if(isset($_GET['path']))
{
$url = $_GET['path'];
$type = "application/pdf";
$completePath = "http://www.webweb.infinityfreeapp.com/lichi/";
$visibleName = "$url";
$completePath .= $url;
// Force download
header("Content-disposition: attachment; filename=$visibleName");
header("Content-Type: application/force-download");
header("Content-Transfer-Encoding: $type\n");
// header("Content-Length: ".filesize($completePath));
header("Pragma: no-cache");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0, public");
header("Expires: 0");
readfile($completePath);
die();
}
I comment Content-Length because it crash system in uncomment
Java code
OkHttpClient client = new OkHttpClient();
String url = "http://www.webweb.infinityfreeapp.com/lichi/download.php?path=Add.jpg";
Call call = client.newCall(new Request.Builder().url(url).get().build());
Response response = call.execute();
if (response.code() == 200 || response.code() == 201) {
Headers responseHeaders = response.headers();
for (int i = 0; i < responseHeaders.size(); i++)
Log.d(LOG_TAG, responseHeaders.name(i) + ": " + responseHeaders.value(i));
String str = response.body().string();
}
Here str contain above html file information instead Add.jpg file data. so please give answer
good question
Autually if we send a get request to
http://www.webweb.infinityfreeapp.com/lichi/download.php?path=Add.jpg
we get the right resutl just like
<html><body><script>document.cookie="_test=9e105a99e90025d241c180c29fad3231 ; expires=Thu, 31-D...";</script></body></html> .
we can get a file in browser, because browser can parse html ,
when browser get the string result which is a html page, it create another request with a new Header (Cookie=_test=9e105a99e90025d241c180c29fad3231), and with the Cookie, we get an image file from server.
Thanks for quick and good solution.
i just add header as:-
.header("Cookie", "_test=9e105a99e90025d241c180c29fad3231")
and send again with above code, actual result come

How to read and parse a multipart response as a stream?

I am creating a java process to download WebEx recordings using their NBR API's NBRFileOpenService call. It returns a multipart response with the recording file contents attached. I have it somewhat working with the code below. However, when the recording file is large enough, I get OutOfMemoryError exception.
It is quite common for the recordings to be large and if the API only returned the file alone, I could just stream the download, however I'm not so sure how I can safely handle the multipart response. So I'm wondering if there is any way to read the file metadata as well as save the binary content to a file without holding the entire response in memory.
API Response Format:
------=_Part_674_458057647.1593732813745
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: binary
Content-Id: <AD79B5747EFC01CDDA9A281BA8CDEF0C>
[SOAP RESPONSE]
------=_Part_674_458057647.1593732813745
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
Content-Id: <C498AB4664B57130F869695A1C5B584E>
[FILE METADATA]
------=_Part_674_458057647.1593732813745
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
Content-Id: <003D9EBA1E491CE2E9E5903C996EFD4C>
[BINARY FILE CONTENT]
------=_Part_674_458057647.1593732813745--
My Code:
public void retrieveRecordingFile(String uri, String recordId, String serviceType) throws Exception {
HttpClient httpClient = generateHttpClient();
HttpPost httpPost = new HttpPost(uri);
httpPost.addHeader("Content-Type", ContentType.APPLICATION_XML.getMimeType());
httpPost.addHeader("SOAPAction", "NBRFileOpenService");
String requestXml = buildNBRDownloadFileXml(recordId, serviceType);
HttpEntity httpEntity = new ByteArrayEntity(requestXml.getBytes(Charset.forName("UTF-8")));
httpPost.setEntity(httpEntity);
HttpResponse httpResponse = httpClient.execute(httpPost);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
MimeMultipart mimeMultipart = new MimeMultipart(new ByteArrayDataSource(httpResponse.getEntity().getContent(), "multipart/form-data"));
String filename = null;
File targetFile = null;
for (int i = 0; i < mimeMultipart.getCount(); i++) {
if (i == 1) {
filename = retrieveFileName(mimeMultipart.getBodyPart(i).getInputStream());
} else if (i == 2) {
targetFile = new File(DOWNLOAD_DIR + filename);
FileUtils.copyInputStreamToFile(mimeMultipart.getBodyPart(i).getInputStream(), targetFile);
}
}
}
}
Any help is truly appreciated.

Attachement's name encoding fails

I try to send an email with an attachment (A pdf file), but the receiver receives a file with a different name and without the .pdf ending. The name of the file is in Greek..
try {
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress("from#mail.com"));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(mail));
message.setSubject(title,"utf-8");
// Create the message part
BodyPart messageBodyPart = new MimeBodyPart();
// Now set the actual message
messageBodyPart.setText("This is message body");
// Create a multipar message
Multipart multipart = new MimeMultipart();
// Set text message part
multipart.addBodyPart(messageBodyPart);
// Part two is attachment
messageBodyPart = new MimeBodyPart();
String filename = "file.pdf";
String f = name + " Πρόγραμμα Ιανουάριος 2016.pdf"; // the desired name of the file
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(MimeUtility.encodeText(f, "UTF-8", null));
multipart.addBodyPart(messageBodyPart);
// Send the complete message parts
message.setContent(multipart);
Transport.send(message);
System.out.println("Mail " + mail +" sent");
} catch (MessagingException e) {
throw new RuntimeException(e);
}
the name is a string variable and is getting a value previously. The strange is that if I have String f = name + " αααα.pdf" the receiver is getting a pdf succesfully with the name Ρουβάς αααα.pdf but if i have this String f = name + " Πρόγραμμα Ιανουάριος 2016.pdf"; he doesn't. He is getting sth like
=_UTF-8_B_zpzOtc Dz4POsc67zrHPgiDOmc6xzr3Ov8 FzqzPgc65zr_Pgi___ ___filename_1=__5wZGY=_=
I added the message.writeTo(System.out); and I got:
MIME-Version: 1.0
Content-Type: multipart/mixed;
bou
ndary="----=_Part_0_1825884453.1457025565509"
------=_Part_0_1825884453.1457025565509
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
This is message body
------=_Part_0_1825884453.1457025565509
Content-Type: application/octet-stream;
name*0="=?UTF-8?B?zpzOtc+Dz4POsc67zrHPgiDOmc6xzr3Ov8+FzrHPgc6vzr/Pgi";
name*1="Ay?=
=?UTF-8?B?MDE2zpnOsc69zr/Phc6sz4HOuc6/z4IgMjAxNi5wZGY=?";
name*2="="
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename*0="=?UTF-8?B?zpzOtc+Dz4POsc67zrHPgiDOmc6xzr3Ov8+FzrHPgc6vzr/Pgi";
filename*1="Ay?=
=?UTF-8?B?MDE2zpnOsc69zr/Phc6sz4HOuc6/z4IgMjAxNi5wZGY=?";
filename*2="="
with props.setProperty("mail.mime.encodeparameters", "false"); or true
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="----=_Part_0_797681969.1457074816557"
------=_Part_0_797681969.1457074816557
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
This is message body
------=_Part_0_797681969.1457074816557
Content-Type: application/octet-stream; name="?????????? 2016.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename*=Cp1252''%3F%3F%3F%3F%3F%3F%3F%3F%3F%3F%202016.pdf
Because you're encoding the filename yourself, you're using the non-standard MIME encoding format, as described in the JavaMail FAQ. That non-standard encoded text is then being split into multiple parameters using the standard RFC 2231 technique. It's this mix of non-standard and standard format that's probably causing the confusion for the mail reader.
Try letting JavaMail do the encoding for you by removing the call to MimeUtility.encodeText. If that doesn't work, set the System property mail.mime.encodeparameters to false to disable the RFC 2231 encoding.

Java AJAX server, how to zip JSON responses

I have a large response which is a JSON object at least 88Kb, I am having problems receiving this data on the clients.
I would like to zip the content in the Java application and send back the zip, I've done this before when using PHP on the server to zip large content and the browser then unzips it.
At present the JSON string is built up in a StringBuilder object. If this idea is flawed what else could I do? The JSON object contains status information for a large system and I need frequent updates to be sent.
Edit...I've progressed the problem, if the size of the JSON is > 512 bytes then I pass the StringBuffer onto the function below:
public StringBuilder zipStringBuilder(StringBuilder sbSource) {
StringBuilder sbZipped = null;
try {
byte[] arybytSource = sbSource.toString().getBytes();
byte[] arybytBuffer = new byte[ZIP_BUFFER];
Deflater objDeflater = new Deflater();
objDeflater.setInput(arybytSource);
ByteArrayOutputStream baos = new ByteArrayOutputStream(arybytSource.length);
objDeflater.finish();
while( !objDeflater.finished() ) {
int intCount = objDeflater.deflate(arybytBuffer);
baos.write(arybytBuffer, 0, intCount);
}
baos.close();
sbZipped = new StringBuilder();
sbZipped.append(baos.toString());
} catch (IOException e) {
e.printStackTrace();
}
return sbZipped;
}
The HTTP headers are as follows:
HTTP/1.0 200
Date: Fri Nov 13 14:47:06 GMT 2015
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT
Access-Control-Allow-Credentials: true
Keep-Alive: timeout=2, max=100
Cache-Control: no-cache
Pragma: no-cache
Content-Encoding: zip
Content-type: application/json;charset=utf-8
But I don't receive this or the browser doesn't understand it?
I've also tried:
Content-Encoding: gzip
With same result.
If your server is behind apache web server turn on the
apache inflate command

Categories