I need to receive multipart/form-data response
but i have no idea on how to parse this kind of response
For example
--mf8sckatxs4PpMnOLF6ltSv26ZJc5qxy9qq
Content-Disposition: form-data; name="arguments"
Content-Type: text/plain;charset=UTF-8
Content-Length: 311
[{"code":200,"message":"123"}]
Content-Disposition: form-data; name="_0"; filename="0_BODY_feature"
Content-Type: application/octet-stream
Content-Length: 407
binarydata
Since you're using Spring you already have the Apache fileupload and http classes available. MultipartStream is designed to be attached to an incoming byte stream and can provide progress updates as data arrives.
This simple example illustrates a non-streaming scenario where you've already buffered the whole incoming body.
byte[] yourResponse = ... // the whole response as a byte array
String yourContentType = ... // the Content-Type header string
ContentType contentType = ContentType.parse(yourContentType);
MultipartStream multipartStream = new MultipartStream(
new ByteArrayInputStream(yourResponse),
contentType.getParameter("boundary").getBytes(),
1024, // internal buffer size (you choose)
null); // progress indicator (none)
boolean nextPart = multipartStream.skipPreamble();
while (nextPart) {
ByteArrayOutputStream output = new ByteArrayOutputStream();
String partHeaders = multipartStream.readHeaders();
multipartStream.readBodyData(output);
// do something with the multi-line part headers
// do something with the part 'output' byte array
nextPart = multipartStream.readBoundary();
}
Add exception handling as required.
You can store and separate those values in an Array of Strings:
String[] array = "allyourinputtext".split(";");
This will separate the values after a semicolon. Then, you can access each value by doing this:
String content = array[0];
String name = array[1];
...
This doesn't solve the WHOLE problem(since not all values are separated by semicolons), but you can play with the arguments you pass to split() to separate your values.
Note: If you want to parse a String to int (the length value for example) you can use:
int length = Integer.parseInt(array[index];
Related
When my page gets hit from a third party page, I get the below data in request payload:
Content-type: multipart/form-data, boundary----------14048
Content-Length = 590
----------14048
Content-disposition: form-data; name ="xyz"
{"abc":"lmn","def":"ghi"}
----------14048
I need to read the JSON string from this parameter in my Java class. How can I do that?
My current code looks like this:
IRequestParameters requestParameters = getRequest().getPostParameters();
if (requestParameters != null && requestParameters.getParameterNames().contains( "abc" )&&requestParameters.getParameterValue( "abc" ) != null){
value = requestParameters.getParameterValue( "abc" ).toString();
}
Thanks in advance.
First, you need to parse multipart form data in Wicket:
MultipartServletWebRequest multiPartRequest =
webRequest.newMultipartWebRequest(getMaxSize(), "ignored");
// multiPartRequest.parseFileParts(); // this is needed after Wicket 6.19.0+
IRequestParameters params = multiPartRequest.getRequestParameters();
Then you need to parse the JSON fragment, one way to do that is by using org.json.
import org.json.*;
JSONObject jsondict = new JSONObject(params.getParameter("xyz");
Then you need to get the JSON parameter you are interested in:
string payload = jsondict.getString("abc");
The below code works fine for me.
HttpSevletRequest request = (HttpSevletRequest )getRequest.getContainerRequest();
try{
InputStreamReader inputReader = new InputStreamReader(request.getInputStream());
BufferedReader reader = new BufferedReader(inputReader );
for(String line;(line = reader.readLine())!=null;){
if(line.contains("abc")){
//perform task....
}
}
}catch(IOException e){
//logs
}
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
I am currently working with java mail api . I need to list the attachment details also wants remove the attachment from some emails and forward it to others. So i'm trying to find out the Attachment ID. How can i do it? Any suggestion will be appreciate!!!
Does this help?
private void getAttachments(Part p, File inputFolder, List<String> fileNames) throws Exception{
String disp = p.getDisposition();
if (!p.isMimeType("multipart/*") ) {
if (disp == null || (disp != null && (disp.equalsIgnoreCase(Part.ATTACHMENT) || disp.equalsIgnoreCase(Part.INLINE)))) {
String fileName = p.getFileName();
File opFile = new File(inputFolder, fileName);
((MimeBodyPart) p).saveFile(opFile);
fileNames.add(fileName);
}
}
}else{
Multipart mp = (Multipart) p.getContent();
int count = mp.getCount();
for (int i = 0; i < count; i++){
getAttachments(mp.getBodyPart(i),inputFolder, fileNames);
}
}
}
There ain't anything as an attachment ID. What your mail client displays as a message with attached contents, is really a MIME Multipart and looks like this (sample source):
From: John Doe <example#example.com>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="XXXXboundary text"
This is a multipart message in MIME format.
--XXXXboundary text
Content-Type: text/plain
this is the body text
--XXXXboundary text
Content-Type: text/plain;
Content-Disposition: attachment; filename="test.txt"
this is the attachment text
--XXXXboundary text--
Important things to note:
Every part in a multipart has a Content-Type
Optionally, there can be a Content-Disposition header
Single parts can be themselves multipart
Note that there is indeed a Content-ID header, but I don't think it's what you are looking for: for example, it is used in multipart/related messages to embed image/*s and text from a text/html in the same email message. You have to understand how it works and if it's used in your input.
I think your best option is to examine the Content-Disposition and the Content-Type header. The rest is guesswork, and without actual requirement one can't help with the code.
Try using the Apache Commons Email package which has a MimeMessageParser class. With the parser you can get the content id (which could be used to identify the attachment) and attachments from the email message like so:
Session session = Session.getInstance(new Properties());
ByteArrayInputStream is = new ByteArrayInputStream(rawEmail.getBytes());
MimeMessage message = new MimeMessage(session, is);
MimeMessageParser parser = new MimeMessageParser(message);
// Once you have the parser, get the content ids and attachments:
List<DataSource> attachments = parser.getContentIds.stream
.map(id -> parser.findAttachmentByCid(id))
.filter(att -> att != null)
.collect(Collectors.toList());
I have created a list here for the sake of brevity, but instead, you could create a map with the contentId as the key and the DataSource as the value.
Take a look at some more examples for using the parser in java here, or some code I wrote for a scala project here.
Given an HTTP request header, does anyone have suggestions or know of existing code to properly parse the header? I am trying to do this with Core Java only, no third party libs
Edit:
Trying to find key fields from this String for example:
GET / HTTP/1.1User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15Host: localhost:9000Accept: /
Want to parse out the Method and method
I wrote a library, RawHTTP, whose only purpose is to parse HTTP messages (requests and responses).
If you don't want to use a library, you could copy the source into your own code base, starting form this: https://github.com/renatoathaydes/rawhttp/blob/a6588b116a4008e5b5840d4eb66374c0357b726d/rawhttp-core/src/main/java/com/athaydes/rawhttp/core/RawHttp.java#L52
This will split the lines of the HTTP message all the way to the end of the metadata sections (start-line + headers).
With the list of metadata lines at hand, you can then call the parseHeaders method, which will create the headers for you. You can easily adapt that to just return a Map<String, List<String>> to avoid having to also import the header classes.
That said... RawHTTP has no dependencies, so I would just use it instead :) but up to you.
Start by reading and understanding the HTTP specification.
The request line and headers are separated by CR LF sequences (bytes with decimal value 13 and 10), so you can read the stream and separate out each line. I believe that the headers must be encoded in US-ASCII, so you can simply convert bytes to characters and append to a StringBuilder (but check the spec: it may allow ISO-8859-1 or another encoding).
The end of the headers is signified by CR LF CR LF.
Your concatenated one-line string is not a HTTP header.
A proper HTTP request message should be look like this (not always)
GET / HTTP/1.1 CRLF
Host: localhost:9000 CRLF
User-Agent: curl/7.19.7 blar blar CRLF
Accept: */* CRLF
Content-Length: ?? CRLF
...: ... CRLF
CRLF
octets
See here http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html
If you want implement a HTTP server without any help of Sevlets, JavaEE Containers, you should use Sockets.
Read the first line [Request-Line = Method SP Request-URI SP HTTP-Version CRLF]
Read the request header line by line till you got the blank line
For each header line you can parse [fieldName: fieldValue]
Read the entity body.
This is NOT the only case for HTTP message contracts.
I'm using the guava library to include preconditions for my methods. You can remove them in favor of null checks.
/**
* #return a string consisting of the HTTP headers, concatenating the keys and values delimited by
* CFLR (empty line) capable of serialization to the database.
*/
public static final String httpHeadersToString(final HttpResponse httpResponse) {
Preconditions.checkNotNull(httpResponse);
Preconditions.checkNotNull(httpResponse.getAllHeaders());
final Header[] allHeaders = httpResponse.getAllHeaders();
StringBuffer sb = new StringBuffer();
int index = 0;
while(index < allHeaders.length) {
Header header = allHeaders[index];
sb.append(header.getName())
.append(System.getProperty("line.separator"))
.append(header.getValue());
if (++index < allHeaders.length) {
sb.append(System.getProperty("line.separator"));
}
}
return sb.toString();
}
/**
* #return reconstruct HTTP headers from a string, delimited by CFLR (empty line).
*/
public final HttpHeaders stringToHttpHeaders(final String headerContents) {
HttpHeaders httpHeaders = new HttpHeaders();
final String[] tempHeaderArray = headerContents.split(System.getProperty("line.separator"));
int i = 0;
while (i + 1 <= tempHeaderArray.length) {
httpHeaders.add(tempHeaderArray[i++], tempHeaderArray[i++]);
}
return httpHeaders;
}
I'm using URL.openConnection() to download something from a server. The server says
Content-Type: text/plain; charset=utf-8
But connection.getContentEncoding() returns null. What up?
The value returned from URLConnection.getContentEncoding() returns the value from header Content-Encoding
Code from URLConnection.getContentEncoding()
/**
* Returns the value of the <code>content-encoding</code> header field.
*
* #return the content encoding of the resource that the URL references,
* or <code>null</code> if not known.
* #see java.net.URLConnection#getHeaderField(java.lang.String)
*/
public String getContentEncoding() {
return getHeaderField("content-encoding");
}
Instead, rather do a connection.getContentType() to retrieve the Content-Type and retrieve the charset from the Content-Type. I've included a sample code on how to do this....
String contentType = connection.getContentType();
String[] values = contentType.split(";"); // values.length should be 2
String charset = "";
for (String value : values) {
value = value.trim();
if (value.toLowerCase().startsWith("charset=")) {
charset = value.substring("charset=".length());
}
}
if ("".equals(charset)) {
charset = "UTF-8"; //Assumption
}
This is documented behaviour as the getContentEncoding() method is specified to return the contents of the Content-Encoding HTTP header, which is not set in your example. You could use the getContentType() method and parse the resulting String on your own, or possibly go for a more advanced HTTP client library like the one from Apache.
Just as an addition to the answer from #Buhake Sindi. If you are using Guava, instead of the manual parsing you can do:
MediaType mediaType = MediaType.parse(httpConnection.getContentType());
Optional<Charset> typeCharset = mediaType.charset();