My android app uses an API which sends a multipart HTTP request. I am successfully getting the response like so:
post.setEntity(multipartEntity.build());
HttpResponse response = client.execute(post);
The response is the contents of an ebook file (usually an epub or mobi). I want to write this to a file with a specified path, lets says "/sdcard/test.epub".
File could be up to 20MB, so it'll need to use some sort of stream, but I can just can't wrap my head around it. Thanks!
well it is a simple task, you need the WRITE_EXTERNAL_STORAGE use permission.. then simply retrieve the InputStream
InputStream is = response.getEntity().getContent();
Create a FileOutputStream
FileOutputStream fos = new FileOutputStream(new File(Environment.getExternalStorageDirectory(), "test.epub"))
and read from is and write with fos
int read = 0;
byte[] buffer = new byte[32768];
while( (read = is.read(buffer)) > 0) {
fos.write(buffer, 0, read);
}
fos.close();
is.close();
Edit, check for tyoo
First is the method:
public HttpResponse setHTTPConnection() throws IOException, NullPointerException, URISyntaxException {
HttpClient client = HttpClientBuilder.create().build();
HttpRequestBase requestMethod = new HttpGet();
requestMethod.setURI(new URI("***FileToDownlod***"));
BasicHttpContext localContext = new BasicHttpContext();
return client.execute(requestMethod, localContext);
}
Second is an actual code:
File downloadedFile = new File("filePathToSave");
HttpResponse fileToDownload = setHTTPConnection();
try {
FileUtils.copyInputStreamToFile(fileToDownload.getEntity().getContent(), downloadedFile);
} finally {
fileToDownload.getEntity().getContent().close();
}
Please make sure to change "filePathToSave" to where to save the file and
"FileToDownlod" to from where to download accordingly.
"filePathToSave" is where you want to save the file, if you choose to save it locally then you can simply point to the desktop but don't forget to give a name to your file like "/Users/admin/Desktop/downloaded.pdf" (in Mac).
"FileToDownlod" is in the form of URL e.g "https://www.doesntexist.com/sample.pdf"
Don't panic as the second piece will ask to declare in throws clause or catch multiple exceptions. This piece of code was for a specific purpose please customize for your own need.
As you said response is content of book or simple meaning that you are getting response as file but not able to save response as file.
Use this
HttpResponse<Path> response = client.send(request, HttpResponse.BodyHandlers.ofFile(Paths.get("/sdcard/test.epub"));
Related
I'm writing a program that builds stuff in a GUI (blah blah blah... irrelevant details), and the user is allowed to export that data as a .tex file which can be compiled to a PDF. Since I don't really want to assume they have a TeX environment installed, I'm using an API (latexonline.cc). That way, I can construct an HTTP GET request, send it to the API, then (hopefully!) return the PDF in a byte-stream. The issue, though, is that when I submit the request, I'm only getting the page data back from the request instead of the data from the PDF. I'm not sure if it's because of how I'm doing my request or not...
Here's the code:
... // preceding code
DataOutputStream dos = new DataOutputStream(new FileOutputStream("test.pdf"));
StringBuilder httpTex = new StringBuilder();
httpTex.append(this.getTexCode(...)); // This appends the TeX code (nothing wrong here)
// Build the URL and HTTP request.
String texURL = "https://latexonline.cc/compile?text=";
String paramURL = URLEncoder.encode(httpTex.toString(), "UTF-8");
URL url = new URL(texURL + paramURL);
byte[] buffer = new byte[1024];
try {
InputStream is = url.openStream();
int bufferLen = -1;
while ((bufferLen = is.read(buffer)) > -1) {
this.getOutputStream().write(buffer, 0, bufferLen);
}
dos.close();
is.close();
} catch (IOException ex) {
ex.printStackTrace();
}
Edit: Here's the data I'm getting from the GET request:
https://pastebin.com/qYtGXUsd
Solved! I used a different API and it works perfectly.
https://github.com/YtoTech/latex-on-http
Is it possible to use the java URL.openStream() method to read the file into an input stream when the URL is a query string rather than a direct link to a file? E.g. the code I have is:
URL myURL = new URL("http://www.test.com/myFile.doc");
InputStream is = myURL.openStream();
This works fine for a direct file link. But what if the URL was http://www.test.com?file=myFile.doc ? Would I still be able to obtain the file stream from the server response?
Thanks!
Generally YES, it will work.
But note that URL.openStream() method doesn't follow redirects and not so agile with specifying some additional HTTP behaviours: request type, headers, etc.
I'd recommend to use Apache HTTP Client instead:
final CloseableHttpClient httpclient = HttpClients.createDefault();
final HttpGet request = new HttpGet("http://any-url");
try (CloseableHttpResponse response = httpclient.execute(request)) {
final int status = response.getStatusLine().getStatusCode();
if (status == 200) {
final InputStream is = response.getEntity().getContent();
} else {
throw new IOException("Got " + status + " from server!");
}
}
finally {
request.reset();
}
The URL class works for any url, including:
new URL("http://www.example.com/");
new URL("file://C/windows/system32/cmd.exe");
new URL("ftp://user:password#example.com/filename;type=i");
Its up to the application to do something with the data, for example download the data, or treat it as plain text.
I am sending images from my android client to java jersey restful service and I succeded in doing that.But my issue is when I try to send large images say > 1MB its consumes more time so I like to send image in CHUNKS can anyone help me in doing this.How to send(POST) image stream in CHUNKS to server
references used :
server code & client call
server function name
/*** SERVER SIDE CODE****/
#POST
#Path("/upload/{attachmentName}")
#Consumes(MediaType.APPLICATION_OCTET_STREAM)
public void uploadAttachment(
#PathParam("attachmentName") String attachmentName,
#FormParam("input") InputStream attachmentInputStream) {
InputStream content = request.getInputStream();
// do something better than this
OutputStream out = new FileOutputStream("content.txt");
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {
// whatever processing you want here
out.write(buffer, 0, len);
}
out.close();
return Response.status(201).build();
}
/**********************************************/
/**
CLIENT SIDE CODE
**/
// .....
client.setChunkedEncodingSize(1024);
WebResource rootResource = client.resource("your-server-base-url");
File file = new File("your-file-path");
InputStream fileInStream = new FileInputStream(file);
String contentDisposition = "attachment; filename=\"" + file.getName() + "\"";
ClientResponse response = rootResource.path("attachment").path("upload").path("your-file-name")
.type(MediaType.APPLICATION_OCTET_STREAM).header("Content-Disposition", contentDisposition)
.post(ClientResponse.class, fileInStream);
You should split the file in the client and restore part of the file in the server.
and after that you should merge the files together. Take a look at split /merge file on coderanch
Enjoy ! :)
Another path is available, if you don't want to code too much consider using :
file upload apache that is great ! :)
I have an Android device. I want to fill a form in my app, with edittexts etc (one of these fields would take the path of an image on the SDCard). I want these form contents to be the data for an HTML form in an external website where this file (from the SD Card) needs to be uploaded. The HTML form has an upload button. I do not want to show this HTML webpage to my android app users. Is there any way to do this? Please let me know! Thanks!
EDIT: I've looked through many websites and I understand that I should use a HttpPost. I have a few doubts though:
1. What is the url that you use in HttpPost- Is it the url which contains the form, or the url which the form redirects to.
2. In a multipartentity, what is the first parameter in addPart? Is it the ID given to the field or the name?
3. How does the HttpPost know which form it should go to?
Well, you need to make a MultiPart Http Post. You could use this sample:
HttpClient httpClient = new DefaultHttpClient();
HttpPost postRequest = new HttpPost("target_link");
MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
reqEntity.addPart("data1", new StringBody("Data1"));
reqEntity.addPart("data2", new StringBody("Data2"));
reqEntity.addPart("data3",new StringBody("Data3"));
try{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.JPEG, 80, bos);
byte[] data = bos.toByteArray();
ByteArrayBody bab = new ByteArrayBody(data, "forest.jpg");
reqEntity.addPart("picture", bab);
}
catch(Exception e){
//Log.v("Exception in Image", ""+e);
reqEntity.addPart("picture", new StringBody(""));
}
postRequest.setEntity(reqEntity);
HttpResponse response = httpClient.execute(postRequest);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
String sResponse;
StringBuilder s = new StringBuilder();
while ((sResponse = reader.readLine()) != null) {
s = s.append(sResponse);
}
Personally, I prefer to use Spring for Android as that is easier to configure. Here's a link with a multi-part Http Post.
Good luck!
I am writing my own implementation of the Google Drive client for the Android and I am using the docs list api. Recently I've encountered a following problem:
At first I was using the HttpURLConnection to upload the file but it seems like it writes the data to the socket after a call to getResponseCose(), not when I am writing to the connection's OutputStream, which is a must for me.
Then I've switched to the Apache HttpClient but I'm still getting a 400 response, not sure why. Maybe you will be able to help me. Here is the code used to upload a file.
String putUrl = conn.getHeaderField("Location");//from the previous request
final HttpClient client = new DefaultHttpClient();
final HttpPut put = new HttpPut(putUrl);
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
put.addHeader("Content-Type", mime==null?"file":mime);
//put.addHeader("Content-Length", String.valueOf(length));
put.addHeader("Content-Range", "bytes 0-"+(length-1)+"/"+length);
put.addHeader("GData-Version", "3.0");
put.addHeader("Authorization", getAuthorizationProperty());
entity.addPart("content", new InputStreamBody(in, name));
put.setEntity(entity);
HttpResponse resp = client.execute(put);
int response = resp.getStatusLine().getStatusCode();
if(response == HttpStatus.SC_CREATED){
lastCreated = parseSingleXMLEntry(resp.getEntity().getContent());
}
Exactly the same headers worked for HttpURLConnection. Maybe the entity is wrong?
Ok, the solution is quite simple, hope it will be useful for someone.
I had to delete all lines which added headers to the request. After that I've added the mime type to the InputStreamBody constructor and overriden the getContentLength() method to provide stream length. Finally it looks like this:
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
entity.addPart("content", new InputStreamBody(in, ,mime, name){
#Override
public long getContentLength() {
return length;
}
});
put.setEntity(entity);
HttpResponse resp = client.execute(put);
And that's all.