OkHttp3 response string show html file instaed of download file data - java

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

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!

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.

download a file from rest api is giving me some garbage value

I am trying to download a file from rest API, I am writing code in Java and react. but when i call that rest api it is not downloading that file instead gives me some garbage
#POST
#Path("/{loginId}")
#Produces(MULTIPART_FORM_DATA)
#Consumes(APPLICATION_JSON)
public Response downloadExportedFile(#PathParam("loginId") String loginId, ExportFileDTO fileDetails) {
File exportFolder = new File("C://directory");
File[] listOfFiles = exportFolder.listFiles();
for (File listOfFile : listOfFiles) {
if (listOfFile.getName().equals(fileDetails.getFileName())) {
InputStream is = new FileInputStream(listOfFile.getAbsolutePath());
byte[] buffer = IOUtils.toByteArray(is);
return Response.ok(listOfFile)
.header("content-disposition", "attachment; filename=" + new File(listOfFile.getName()).getName())
.type(MediaType.APPLICATION_OCTET_STREAM_TYPE).build();
}
}
It should download the file instead it is giving me output as
PK!b�h^�[Content_Types].xml �(����N�0E�H�C�-Jܲ#5��Q>�ēƪc[�ii����B�j7���{2��h�nm���ƻR����U^7/���%��rZY�#1__�f��q��R4D�AJ�h>����V�ƹ�Z�9����NV�8ʩ����ji){^��-I�"{�v^�P!XS)bR�r��K�s(�3�`c�0��������7M4�����ZƐk+�|\|z�(���P��6h_-[�#�!���Pk���2n�}�?�L��� ��%���d����dN"m,�ǞDO97�~��ɸ8�O�c|n���E������B��!$}�����;{���[����2���PK!�U0#�L_rels/.rels �(���MO�0��H�����ݐBKwAH�!T~�I����$ݿ'T�G�~����<���!��4��;#�w����qu*&r�Fq���v�����GJy(v��*����K��#F��D��.W ��=��Z�MY�b���BS�����7��ϛז��
?�9L�ҙ�sbgٮ|�l!��USh9i�b�r:"y_dl��D���|-N��R"4�2�G�%��Z�4�˝y�7 ë��ɂ�����PK!
You have to change the associated mimetype by changing the the parameter of the #Produces annotation which basically describes what type of data you transmit in your response.
It should become:
#Produces("application/vnd.ms-excel")
According to this other stackoverflow question you should change the #Produces annotation to #Produces(MediaType.APPLICATION_OCTET_STREAM).
According to this second stackoverflow question you are asking an impossible question.
Out of curiosity I reproduced your problem here : see the full gist
If you change #POST to #GET it starts working
If you keep #POST, it has to be posted from a real form and can't post application/json
Finally, posting application/json means React is doing a programmatic XmlHTTPRequest. The above gist shall convince you there is no user prompt in that case
When you say it 'is giving me output', you're not telling where and how the post was requested . You will have to adapt that part.
actually It is APPLICATION_OCTET_STREAM response for a file. we have to handle download functionality at client side AS per Nate's answer here, the response of Ajax request is not recognized by a browser as a file. It will behave in the same way for all Ajax responses. You need to trigger the download popup manually.
downloadFile(fileDetails) {
let username = getUserName();
return fetch(`/files/${username}`, {
method: 'POST',
body: JSON.stringify(fileDetails)
}).then(response => {
return response.blob();
}).then(response => {
let blob = new Blob([response], {type: 'application/octet-stream'});
let fileUrl = window.URL.createObjectURL(blob);
Files.triggerDownload(fileUrl, fileDetails.fileName);
}).catch((error) => {
//myerror
});
}
static triggerDownload(url, fileName) {
let a = document.createElement('a');
a.setAttribute('href', url);
a.setAttribute('download', fileName);
a.click();
}
This will download the file at client machine

Http response through service sends content (mime) type in text/html but not application/json

My application using Oauth for basecam api. I am trying to get Httpresponse into json format but it revert into plain html (text/html) content-type. so there is no method to parse HTML content and get the token from basecamp. This is not homework but a small R&D to quick start Oauth protocol. as am new to oauth.
//HERE -> final String JSON_CONTENT = "application/json"
String contentType = OAuthConstants.JSON_CONTENT;
if (response.getEntity().getContentType() != null) {
contentType = response.getEntity().getContentType().getValue();
//BELOW -> getting contentType is in "text/html; utf-8
System.out.println(response.getEntity().getContentType().getValue()); //text/html; charset=utf-8
}
if (contentType.contains(OAuthConstants.JSON_CONTENT)) {
return handleJsonResponse(response);
} else
if (contentType.contains(OAuthConstants.URL_ENCODED_CONTENT)) {
return handleURLEncodedResponse(response);
} else
if (contentType.contains(OAuthConstants.XML_CONTENT)) {
return handleXMLResponse(response);
}
else {
// Unsupported Content type
throw new RuntimeException(
"Cannot handle "
+ contentType
+ " content type. Supported content types include JSON, XML and URLEncoded");
}
So above lines explain very well that control won't come is json, xml or url_encoded if-else. Si either i need to parse text/html into json or xml response or i have to create another method name handleHtmlResponse(). what way it would be continent to get contentType.
After the response is set with all the data(header, body ...), commit it by calling ServletResponse#flushBuffer.

Attachment Id of emails in java

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.

Categories