How to download a part of a file from URL in android? - java

I am trying to download a part of file given the download URL using setRequestProperty("Range","bytes=" + startbytes + "-" + endbytes); The following code snippet shows what I am trying to do.
protected String doInBackground(String... aurl) {
int count;
Log.d(TAG,"Entered");
try {
URL url = new URL(aurl[0]);
HttpURLConnection connection =(HttpURLConnection) url.openConnection();
int lengthOfFile = connection.getContentLength();
Log.d(TAG,"Length of file: "+ lengthOfFile);
connection.setRequestProperty("Range", "bytes=" + 0 + "-" + 1000);
The problem is that, an exception is being raised, which says "Cannot set request property after connection is made". Please help me resolve this issue.

Option 1
If you do not need to know the content length:
[Beware, do not call the connection.getContentLength(). If you call that, you will get the exception. If you need to call it, then check the second option]
URL url = new URL(aurl[0]);
HttpURLConnection connection =(HttpURLConnection) url.openConnection();
connection.setRequestProperty("Range", "bytes=" + 0 + "-" + 1000);
//Note that, response code will be 206 (Partial Content) instead of usual 200 (OK)
if(connection.getResponseCode() == HttpURLConnection.HTTP_PARTIAL){
//Your code here to read response data
}
Option 2
If you need to know the content length:
URL url = new URL(aurl[0]);
//First make a HEAD call to get the content length
HttpURLConnection connection =(HttpURLConnection) url.openConnection();
connection.setRequestMethod("HEAD");
if(connection.getResponseCode() == HttpURLConnection.HTTP_OK){
int lengthOfFile = connection.getContentLength();
Log.d("ERF","Length of file: "+ lengthOfFile);
connection.disconnect();
//Now that we know the content lenght, make the GET call
connection =(HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Range", "bytes=" + 0 + "-" + 1000);
//Note that, response code will be 206 (Partial Content) instead of usual 200 (OK)
if(connection.getResponseCode() == HttpURLConnection.HTTP_PARTIAL){
//Your code here to read response data
}
}

Assuming you're using HTTP for the download, you'll want to use the HEAD http verb and RANGE http header.
HEAD will give you the filesize (if available), and then RANGE lets you download a byte range.
Once you have the filesize, divide it into roughly equal sized chunks and spawn download thread for each chunk. Once all are done, write the file chunks in the correct order.
If you don't know how to use the RANGE header, here's another SO answer that explains how: https://stackoverflow.com/a/6323043/1355166
[EDIT]
To make file into chunks use this, and start the downloading process,
private void getBytesFromFile(File file) throws IOException {
FileInputStream is = new FileInputStream(file); //videorecorder stores video to file
java.nio.channels.FileChannel fc = is.getChannel();
java.nio.ByteBuffer bb = java.nio.ByteBuffer.allocate(10000);
int chunkCount = 0;
byte[] bytes;
while(fc.read(bb) >= 0){
bb.flip();
//save the part of the file into a chunk
bytes = bb.array();
storeByteArrayToFile(bytes, mRecordingFile + "." + chunkCount);//mRecordingFile is the (String)path to file
chunkCount++;
bb.clear();
}
}
private void storeByteArrayToFile(byte[] bytesToSave, String path) throws IOException {
FileOutputStream fOut = new FileOutputStream(path);
try {
fOut.write(bytesToSave);
}
catch (Exception ex) {
Log.e("ERROR", ex.getMessage());
}
finally {
fOut.close();
}
}

Related

File download from url using HttpURLConnection |HTTP 400 if file name contain space

I'm trying to download the files from url(soap request) using http connection, and below is my code, while executing i'm getting http = 400, because of file Name contain space (ac abc.pdf)
String downloadFileName = "ac abc.pdf";
String saveDir = "D:/download";
String baseUrl = "abc.com/AttachmentDownload?Filename=";
URL url = new URL(baseUrl + downloadFileName);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setReadTimeout(60 * 1000);
connection.setConnectTimeout(60 * 1000);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/octet-stream");
connection.setRequestProperty("SOAPAction", url.toString());
String userCredentials = "user:pass";
connection.setRequestProperty("Authorization", userCredentials);
connection.setDoInput(true);
connection.setDoOutput(true);
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
try (InputStream inputStream = connection.getInputStream()) {
String saveFilePath = saveDir + downloadFileName;
try (FileOutputStream outputStream = new FileOutputStream(saveFilePath)) {
int bytesRead = -1;
byte[] buffer = new byte[BUFFER_SIZE];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
}
while executing the above code getting the below output
responsecode400
response messageBad Request
No file to download. Server replied HTTP code: 400
let me know how can we format the url with the above situation
Spaces and some other symbols are not well tollerated in URL. You need to escape or encode them change your code
URL url = new URL(baseUrl + downloadFileName);
To:
URL url = new URL(baseUrl + URLEncoder.encode(downloadFileName, StandardCharsets.UTF_8.name());
That should resolve your problem. Besides there are Open Source libraries that resolve your issue for you. See Apache commons which is a popular solution. Another solution is MgntUtils library (version 1.5.0.2). It contains class HttpClient that allows you to do things very simple:
httpClient.sendHttpRequestForBinaryResponse(baseUrl + URLEncoder.encode(downloadFileName, StandardCharsets.UTF_8.name()", HttpClient.HttpMethod.POST);
This will return ByteBuffer that contains the response as raw bytes. The same class has method sendHttpRequest to get Textual response. Both methods throw IOException in case of failure. Here is the link to an article that explains where to get MgntUtils library as well as what utilities it has. In the article the HttpClient class is not mentioned (It is a new feature), but the library comes with well written javadoc. So look for javadoc for HttpClient class in that library.

File is not uploded after removing System.out.println("response :: " + conn.getResponseMessage());

Following is my function to upload file GCS :
public void fileUpload(InputStream streamData, String fileName,
String content_type) throws Exception {
byte[] utf8Bytes = fileName.getBytes("UTF8");
fileName = new String(utf8Bytes, "UTF8");
URL url = new URL("http://bucketname.storage.googleapis.com"+"/"+"foldername/"+fileName);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("PUT");
conn.setRequestProperty("Accept", "application/x-www-form-urlencoded");
conn.setRequestProperty("Authorization", "OAuth " + GcsToken.getAccessToken());
conn.setRequestProperty("x-goog-meta-FileName", fileName);
conn.setRequestProperty("x-goog-meta-ContentType", content_type);
OutputStream os = conn.getOutputStream();
BufferedInputStream bfis = new BufferedInputStream(streamData);
byte[] buffer = new byte[1024];
int bufferLength = 0;
// now, read through the input buffer and write the contents to the file
while ((bufferLength = bfis.read(buffer)) > 0) {
os.write(buffer, 0, bufferLength);
}
System.out.println("response :: " + conn.getResponseMessage());// ?????
}
This code works fine to uplaod file, but
After removing last Sysout , it is not uploading file
System.out.println("response :: " + conn.getResponseMessage());
what is reason behind this ?
any help ?
thnaks
You need to close your OutputStream to indicate that you've finished writing the request body:
os.close();
You should also check the response code of the request:
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
// Error handling code here.
}
The reason it was working before is because the getResponseMessage function blocks until the request is finished being sent and the reply is received. Without ever checking the response value, your function just exits and the HTTP request might not be finished sending.
Thanks for this clarification.
I already tried with os.close() also tried with os.flush(). but same problem. :(
at last i have updated my code:
while ((bufferLength = bfis.read(buffer)) > 0) {
os.write(buffer, 0, bufferLength);
}
os.close();
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
//logger
}
Now I am able to upload file.
Thanks again.

How can I make a http partial GET request in Java

I'm trying to make a partial GET request and I expect a 206 response, but I'm still getting 200 OK. How can I make it responded with a 206?
Here is the code I wrote:
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
int start = Integer.parseInt(args[1]);
int end = Integer.parseInt(args[2]);
urlConn.setRequestMethod("GET");
urlConn.setRequestProperty("Range", "bytes=" + start + "-" + end);
if (urlConn.getResponseCode() != HttpURLConnection.HTTP_PARTIAL)
System.out.println ("File cannot be downloaded.");
else
{
String filepath = url.getPath();
String filename = filepath.substring (filepath.lastIndexOf('/') + 1);
BufferedInputStream in = new BufferedInputStream (urlConn.getInputStream());
BufferedOutputStream out = new BufferedOutputStream (new FileOutputStream (filename));
int temp;
while ((temp = in.read()) != -1)
{
out.write ((char)temp);
}
out.flush();
out.close();
System.out.println ("File downloaded successfully.");
}
How can I make it responded with a 206?
You can't force a server to respect your Range headers. The HTTP 1.1 spec says:
"A server MAY ignore the Range header."
You comment:
I know the server does not ignore it. At least shouldn't
Well apparently, the server >>IS<< ignoring the header. Or alternatively, the range that you are requesting encompasses the entire document.

Can't download pdf with java

I'm trying to download a file from
http://aula.au.dk/main/document/document.php?action=download&id=%2F%D8velsesvejledning+2012.pdf
but it dosen't appear to be a pdf, when i try downloading it with this code
import java.io.*;
import java.net.*;
public class DownloadFile {
public static void download(String address, String localFileName) throws IOException {
URL url1 = new URL(address);
byte[] ba1 = new byte[1024];
int baLength;
FileOutputStream fos1 = new FileOutputStream(localFileName);
try {
// Contacting the URL
System.out.print("Connecting to " + url1.toString() + " ... ");
URLConnection urlConn = url1.openConnection();
// Checking whether the URL contains a PDF
if (!urlConn.getContentType().equalsIgnoreCase("application/pdf")) {
System.out.println("FAILED.\n[Sorry. This is not a PDF.]");
} else {
try {
// Read the PDF from the URL and save to a local file
InputStream is1 = url1.openStream();
while ((baLength = is1.read(ba1)) != -1) {
fos1.write(ba1, 0, baLength);
}
fos1.flush();
fos1.close();
is1.close();
} catch (ConnectException ce) {
System.out.println("FAILED.\n[" + ce.getMessage() + "]\n");
}
}
} catch (NullPointerException npe) {
System.out.println("FAILED.\n[" + npe.getMessage() + "]\n");
}
}
}
Can you help me out here?
http://aula.au.dk/main/document/document.php?action=download&id=%2F%D8velsesvejledning+2012.pdf is not a pdf. The website gives an error this is why the script doesn't work:
SQL error in file /data/htdocs/dokeos184/www/main/inc/tool_navigation_menu.inc.php at line 70
As Marti said, the root cause of the problem is the fact that the script fails. I tested your program on a working pdf link, it works just fine.
This wouldn't have helped you in this case, but HttpURLConnection is a specialized subclass of URLConnection that makes communications with an http server a lot easier - eg direct access to error codes, etc.
HttpURLConnection urlConn = (HttpURLConnection) url1.openConnection();
// check the responsecode for e.g. errors (4xx or 5xx)
int responseCode = urlConn.getResponseCode();
2 step process with 2 libraries.
// 1. Use Jsoup to get the response.
Response response= Jsoup.connect(location)
.ignoreContentType(true)
// more method calls like user agent, referer, timeout
.execute();
// 2. Use Apache Commons to write the file
FileUtils.writeByteArrayToFile(new File(path), response.bodyAsBytes());

Java applet to upload a file

I am looking for a Java applet to read a file from client machine and creat a POST request for PHP server uploading.
PHP script on server should receive the file as normal file upload in FORM submit.
I am using the following code. The file contents are passed to PHP script
but they are not correctly converted to an image.
//uploadURL will be a url of PHP script like
// http://www.example.com/uploadfile.php
URL url = new URL(uploadURL);
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setRequestMethod("POST");
con.setDoInput(true);
con.setDoOutput(true);
InputStream is = new FileInputStream("C://img.jpg");
OutputStream os = con.getOutputStream();
byte[] b1 = new byte[10000000];
int n;
while((n = is.read(b1)) != -1) {
os.write("hello" , 0, 5);
test += b1;
}
con.connect();
Here is some code that might help you it's from one of my old projects with a bunch of unrelated stuff removed, take it for what it's worth. Basically, I think the code in your question is missing some parts that the HTTP protocol requires
public class UploaderExample
{
private static final String Boundary = "--7d021a37605f0";
public void upload(URL url, List<File> files) throws Exception
{
HttpURLConnection theUrlConnection = (HttpURLConnection) url.openConnection();
theUrlConnection.setDoOutput(true);
theUrlConnection.setDoInput(true);
theUrlConnection.setUseCaches(false);
theUrlConnection.setChunkedStreamingMode(1024);
theUrlConnection.setRequestProperty("Content-Type", "multipart/form-data; boundary="
+ Boundary);
DataOutputStream httpOut = new DataOutputStream(theUrlConnection.getOutputStream());
for (int i = 0; i < files.size(); i++)
{
File f = files.get(i);
String str = "--" + Boundary + "\r\n"
+ "Content-Disposition: form-data;name=\"file" + i + "\"; filename=\"" + f.getName() + "\"\r\n"
+ "Content-Type: image/png\r\n"
+ "\r\n";
httpOut.write(str.getBytes());
FileInputStream uploadFileReader = new FileInputStream(f);
int numBytesToRead = 1024;
int availableBytesToRead;
while ((availableBytesToRead = uploadFileReader.available()) > 0)
{
byte[] bufferBytesRead;
bufferBytesRead = availableBytesToRead >= numBytesToRead ? new byte[numBytesToRead]
: new byte[availableBytesToRead];
uploadFileReader.read(bufferBytesRead);
httpOut.write(bufferBytesRead);
httpOut.flush();
}
httpOut.write(("--" + Boundary + "--\r\n").getBytes());
}
httpOut.write(("--" + Boundary + "--\r\n").getBytes());
httpOut.flush();
httpOut.close();
// read & parse the response
InputStream is = theUrlConnection.getInputStream();
StringBuilder response = new StringBuilder();
byte[] respBuffer = new byte[4096];
while (is.read(respBuffer) >= 0)
{
response.append(new String(respBuffer).trim());
}
is.close();
System.out.println(response.toString());
}
public static void main(String[] args) throws Exception
{
List<File> list = new ArrayList<File>();
list.add(new File("C:\\square.png"));
list.add(new File("C:\\narrow.png"));
UploaderExample uploader = new UploaderExample();
uploader.upload(new URL("http://systemout.com/upload.php"), list);
}
}
I'd suggest you take a look at Gallery Remote. This is an open source project for uploading photos to a PHP backend. It's a bit more full featured than what you may need, but you should be able to modify the code to your needs fairly easily.
You could also look at JUpload. It's not as full featured, but it is open source and capable of the task.

Categories

Resources