Stream HTTP GET response to file in Mule - java

How do you make a HTTP GET request in Mule, and then stream the response to a file? My application stores the entire response in memory, but the response can be large, so this needs to be fixed. I want to save the response to a temporary file, and then stream the file contents back to the client.
Right now, I'm doing:
String restUrl = "http://www.url.com";
UMOEventContext context = RequestContext.getEventContext();
GetMethod method = new GetMethod(restUrl);
UMOMessage muleMessage = new MuleMessage(method);
muleMessage.setProperty(RestServiceWrapper.REST_SERVICE_URL, restUrl);
UMOMessage result = context.sendEvent(muleMessage, new MuleEndpointURI("vm://identifier")); //OutOfMemoryException
String body = result.getPayloadAsString();
I'm using Mule 1.3.3 and cannot upgrade. Thank you.

Related

In Spring Boot Java Extracting the zip file from response without physically saving it

In Spring Boot the zip file that comes as a response has a corrupted structure before saving, but there is no problem when I save it physically. I need to take the file in the zip file and process the information in the database, but I cannot physically download this file because I am using GCP. How can I extract the file in this zip file that comes as a response?. How can I solve this please help.
Here is what it looks like in response.body() before saving (part of it):
"PK C`iUq �=n 緰) bu_customerfile_22110703_B001_10292121141�]i��������RI%U�v��CJ� ���×��My��y/ίϹ�������=>����}����8���׿}~}~yz�������ͲL��
�o�0�fV�29f�����6΋$K�c$�F��/�8˳�L��_�QaZ-q�F�d4γE�[���(f�8�D�0��2_��P"�I�A��D��4�߂�����D��(�T�$.��<�,���i]Fe�iM�q<ʨ�Olmi�(&���?�y�y4��<��Q�X�ޘp�#�6f-.F����8����"I㢨ҤU]�E��WI� %#������(W�8*0c�p:L��:� �}�G����e<����a�"
Here is the request call:
OkHttpClient client1 = new OkHttpClient().newBuilder()
.build();
MediaType mediaType1 = MediaType.parse("text/plain");
RequestBody body1 = RequestBody.create(mediaType1, "");
Request request1 = new Request.Builder()
.url(vers)
.method("POST", body1)
.addHeader("Cookie", "ASP.NET_SessionId=44dxexdxass5mtf00udjfwns")
.build();
Response response1 = client1.newCall(request1).execute();
String data = response1.body().string();
Would it be a matter of encoding type? String is of type UTF-16 (I think). Try a different datatype that is more like an array/vector of bytes.
Try something like what is mentioned here:
Having trouble reading http response into input stream
Update: Get the response as a stream of bytes and feed it into a ZipInputStream object as shown here https://zetcode.com/java/zipinputstream/#:~:text=ZipInputStream%20is%20a%20Java%20class,both%20compressed%20and%20uncompressed%20entries.
Then iterate over the contained files to find the one you need. Then retrieve the stream associated with the zipped file. Then you can read from there. (I realize that is a bit of handwaving, but it's been a while since I used Zip files and Java.) That should get you down the correct path.

Download file from REST service using JAX-RS client

I am trying to download a file from a REST service using JAX-RS.
This is my code which invokes the download by sending a GET request:
private Response invokeDownload(String authToken, String url) {
// Creates the HTTP client object and makes the HTTP request to the specified URL
Client client = ClientBuilder.newClient();
WebTarget target = client.target(url);
// Sets the header and makes a GET request
return target.request().header("X-Tableau-Auth", authToken).get();
}
However I am facing problems converting the Response into an actual File object. So what I did is the following:
public File downloadWorkbook(String authToken, String siteId, String workbookId, String savePath)
throws IOException {
String url = Operation.DOWNLOAD_WORKBOOK.getUrl(siteId, workbookId);
Response response = invokeDownload(authToken, url);
String output = response.readEntity(String.class);
String filename;
// some code to retrieve the filename from the headers
Path path = Files.write(Paths.get(savePath + "/" + filename), output.getBytes());
File file = path.toFile();
return file;
}
The file which is created is not valid, I debugged the code and noticed that output contains a String like that (much larger):
PK ͢�F���� �[ Superstore.twb�ysI�7����ߡ���d�m3��f���
Looks like binary. Obviously there is something wrong with the code.
How do I get the HTTP response body as a string from the Response object?
Edit:
Quote from the REST API reference about the HTTP response:
Response Body
One of the following, depending on the format of the workbook:
The workbook's content in .twb format (Content-Type: application/xml)
The workbook's content in .twbx format (Content-Type: application/octet-stream)
As you noticed yourself, you're dealing with binary data here. So you shouldn't create a String from your response. Better get the input stream and pipe it to your file.
Response response = invokeDownload(authToken, url);
InputStream in = response.readEntity(InputStream.class);
Path path = Paths.get(savePath, filename);
Files.copy(in, path);
1) I assume by this point you're clear on the difference between "binary file" and "text file". And that you can only capture the latter into a "string".
2) Sebastian gave you excellent advice for capturing a binary file (+1, Sebastian!). VERY IMPORTANT: you should always set the MIME type (Content-Type: xxx/yyy)in cases like this. Here is another link that might be useful.
3) Finally, there are cases where you might WANT to treat "binary" data as text. This is how e-mail attachments work with SMTP (a text protocol). In these cases, you want to use Base64 Encoding. For example: JAX-RS | Download PDF from Base64 encoded data

Download a PDF file via REST service with “Content-Disposition” Header in java

I am trying to download a PDF file from a response of Java REST call after custom authentication check.
I can see downloaded file but it is empty file.
Below is my code snippet.
//Custom HTTPClient
HTTPAuthClient client = new HTTPAuthClient(url,username,password)
Request request = new Request(downloadURL); //I'm downloading file content of an URL.
Response response = client.executeGet(request);
String response1 = response.getResponseBody();
InputStream is = new ByteArrayInputStream(response.getBytes());
response.setContentType("Content-type",application/pdf); //here response is //javax.servlet.HttpServletResponse
response.setHeader("Content-Disposition","attachment;filename="myfile.pdf");
IOUtils.copy(is,response.getOutPutStream());
response.flushBuffer();
With this code I could download the file but when I open the file and verified there is no data.
As part of response body also I can see some data.
Could you please help me out where I'm doing mistake I tried many options but did not find solution.
How can you use setContentType like this
response.setContentType("Content-type",application/pdf);
If only one avalible param in this method is String void setContentType(String type) so your method should be:
response.setContentType("application/pdf");
Java Doc to be sure.

Android - Upload image along with request data

I want to upload an image to my server through an android app however I would also like to pass other data along with the image (authentication, intention, etc.).
I have normally been making requests like so:
http://server/script.php?t=authtoken&j_id=12&... etc
However, I assume I cannot simply tack on another query parameter containing the byte array for the image as that would result in a URL with a size on the order of millions of characters.
&image=001101010010110111010001010101010110100101000101010100010... etc
I'm at a loss as to how I should approach this and would appreciate any suggestions. If I am not able to send the data through an http request, how would I handle the incoming data server-side?
Thanks.
Here's how I got it work for those who may find this in the future.
For this example, let's say we want to query the PHP script upload.php on the root of www.server.com with the parameters t=ABC123 and id=12. Along with this request, we also want to upload an image stored in the java.io.File object img. We will also be expecting a response from the server letting us know whether the upload was successful or not.
ANDROID SIDE
On the android side, you will need the following JARs:
apache-mime4j-core-0.7.2.jar
Availabe here and:
httpclient-4.3.1.jar
httpcore-4.3.jar
httpmime-4.3.1.jar
Availabe here.
Here is a snippet on how to make the multipart request and get a response:
public String uploadRequest(String address, File img)
{
HttpParams p = new BasicHttpParams();
p.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
DefaultHttpClient client = new DefaultHttpClient(p);
HttpPost post = new HttpPost(address);
// No need to add regular params as parts. You can if you want or
// you can just tack them onto the URL as usual.
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addPart("image", new FileBody(img));
post.setEntity(builder.build());
return client.execute(post, new ImageUploadResponseHandler()).toString();
}
private class ImageUploadResponseHandler implements ResponseHandler<Object>
{
#Override
public Object handleResponse(HttpResponse response) throws ClientProtocolException, IOException
{
HttpEntity responseEntity = response.getEntity();
return EntityUtils.toString(responseEntity);
}
}
An example of using this method in the code (assume the variable img has already been declared containing the File object of the image you wish to upload):
// Notice regular params can be included in the address
String address = "http://www.server.com/upload.php?t=ABC123&id=12";
String resp = uploadRequest(address, img);
// Handle response
PHP SIDE
For the server-side script, the text params can be accessed normally through PHP's $_REQUEST object:
$token = $_REQUEST['token'];
$id = $_REQUEST['id'];
And the image that was uploaded can accessed by using the information stored in the PHP $_FILES object (See the PHP docs for more info):
$img = $_FILES['img'];

Setting content length of an HTTP POST request

I am trying to make a Http POST request using apache HTTP client. I am trying to copy contents of an HTTP POST request (received at my application) to another HTTP POST request (initiated from my application to another URL). Code is shown below:
httpPost = new HttpPost(inputURL);
// copy headers
for (Enumeration<String> e = request.getHeaderNames(); e.hasMoreElements();) {
String headerName = e.nextElement().toString();
httpPost.setHeader(headerName, request.getHeader(headerName));
}
BufferedInputStream clientToProxyBuf = new BufferedInputStream(request.getInputStream());
BasicHttpEntity basicHttpEntity = new BasicHttpEntity();
basicHttpEntity.setContent(clientToProxyBuf);
basicHttpEntity.setContentLength(clientToProxyBuf.available());
httpPost.setEntity(basicHttpEntity);
HttpResponse responseFromWeb = httpclient.execute(httpPost);
Basically, I am trying to implement a proxy application which will get a url as parameter, froward the request to the URL and then serve pages etc in custom look and feel.
Here request is HttpServletRequest. I am facing problem in setting content length. Through debugging I found out that clientToProxyBuf.available() is not giving me correct length of input stream and I am getting Http error 400 IE and Error 354 (net::ERR_CONTENT_LENGTH_MISMATCH): The server unexpectedly closed the connection in chrome.
Am I doing it wrong? Is there any other way to achieve it?
The available() function doesn't provide the actual length of the content of the stream, rather
Returns the number of bytes that can be read from this input stream without blocking. (From javadoc)
I would suggest you to first read the whole content from the stream, and then set that to the content, rather than passing the stream object. That way, you will also have the actual length of the content.
It was rather simple and very obvious. I just needed to get content length from header as:
basicHttpEntity.setContentLength(Integer.parseInt(request.getHeader("Content-Length")));

Categories

Resources