How do I download part of a file using Java? - java

I'm using this Java code to download a file from the Internet:
String address = "http://melody.syr.edu/pzhang/publications/AMCIS99_vonDran_Zhang.pdf";
URL url = new URL(address);
System.out.println("Opening connection to " + address + "...");
URLConnection urlC = url.openConnection();
urlC.setRequestProperty("User-Agent", "");
urlC.connect();
InputStream is = urlC.getInputStream();
FileOutputStream fos = null;
fos = new FileOutputStream("myFileName");
int oneChar, count = 0;
while ((oneChar = is.read()) != -1) {
System.out.print((char)oneChar);
fos.write(oneChar);
count++;
}
is.close();
fos.close();
System.out.println(count + " byte(s) copied");
I'd like to know if there is a way for me to download only a part of a file.
For example, for a 5MB file to download the last 2MB.

If the server supports it (and HTTP 1.1 servers should), you can use range requests:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35
Also, reading one character at a time is hugely inefficient - you should be reading in blocks, say 4, 16 or 32 KB.

Please have a look at Java: resume Download in URLConnection

Related

Remote file transfer using java nio

I am trying to use JAVA NIO to transfer a file from host A to client B without having to download the file locally and then giving the client B a link to download the file.
I am running a spark Apache framework and using maven project.
I mapped the request http://localhost:8080/download/hello in Spark using :
get("/download/:id",RequestHandler::downloadHandler);
Inside of the function is the code that downloads the file from :
"https://download.springsource.com/release/STS/3.8.1.RELEASE/dist/e4.6/spring-tool-suite-3.8.1.RELEASE-e4.6-linux-gtk-x86_64.tar.gz"
try {
URL url = new URL("https://download.springsource.com/release/STS/3.8.1.RELEASE/dist/e4.6/spring-tool-suite-3.8.1.RELEASE-e4.6-linux-gtk-x86_64.tar.gz");
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
int respCode = +httpURLConnection.getResponseCode();
System.out.println("response code : "+respCode);
if (respCode == HttpURLConnection.HTTP_OK){
String fileName = "";
String disposition = httpURLConnection.getHeaderField("Content-Disposition");
String contentType = httpURLConnection.getContentType();
int contentLength = httpURLConnection.getContentLength();
if (disposition != null) {
// extracts file name from header field
int index = disposition.indexOf("filename=");
if (index > 0) {
fileName = disposition.substring(index + 10,
disposition.length() - 1);
}
} else {
// extracts file name from URL
fileName = url.toString().substring(url.toString().lastIndexOf("/") + 1,
url.toString().length());
}
System.out.println("Content-Type = " + contentType);
System.out.println("Content-Disposition = " + disposition);
System.out.println("Content-Length = " + contentLength);
System.out.println("fileName = " + fileName);
httpURLConnection.disconnect();
System.out.println("other stuff : ");
System.out.println(url.getHost());
ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream());
FileOutputStream fileOutputStream = new FileOutputStream(fileName);
FileChannel fileChannel = fileOutputStream.getChannel();
fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
fileOutputStream.close();
readableByteChannel.close();
}
} catch (IOException e) {
e.printStackTrace();
}
I fetch the filename and file size using httpURLConnection and then processed to download the file. what I am trying to do is, instead of downloading the file locally using fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE) transfer the file directly to the client.
I did some research and I think it is possible with using Socketchannels but I didn't understand how it is supposed to work.
I also read this article
https://examples.javacodegeeks.com/core-java/nio/java-nio-large-file-transfer-tutorial/
and tried to understand the class Reciever, but it is still not clear to me how.
I would appreciate some guidance. Thank you

file-size difference while downloading file

I'm working on a Java file downloader, so I just downloaded a video file with app and without app, so I saw file-size differences between that files. And I couldn't open the file which I downloaded by using my Java app. When I open them using Notepad++, I saw randomly generated symbols inside. What am I doing so wrong?
http://i.imgur.com/lKaofVg.png - here, as you can see randomly generated question marks there.
http://i.imgur.com/8bLC2R7.png - but in the original file, they doesn't exist.
http://i.imgur.com/H3MGgwl.png - here's the file sizes, I just placed "+" for the generated file.
Here's my code:
String currentRange = "bytes=0-"+num*13107200;
System.out.println(num + " is executing");
URL file = new URL(url);
FileOutputStream stream = new FileOutputStream("tmp"+num+".mp4");
HttpURLConnection urlConnection = (HttpURLConnection) file.openConnection();
urlConnection.setRequestProperty("Range", currentRange);
urlConnection.connect();
BufferedReader in = new BufferedReader(new InputStreamReader(
urlConnection.getInputStream()));
String inputLine;
final PrintStream printStream = new PrintStream(stream);
while ((inputLine = in.readLine()) != null)
printStream.println(inputLine);
in.close();
printStream.close();
I solved by using this code, thanks to this question: Reading binary file from URLConnection and #piet.t
InputStream input = urlConnection.getInputStream();
byte[] buffer = new byte[4096];
int n = - 1;
while ( (n = input.read(buffer)) != -1)
{
stream.write(buffer, 0, n);
}

HttpURLConnection and download large files

I use HttpURLConnection to download files from a url.
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// optional default is GET
con.setRequestMethod("GET");
con.setRequestProperty("Cache-Control", "no-cache");
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
try {
InputStream inputStream = con.getInputStream();
FileOutputStream outputStream = new FileOutputStream("C:\\programs\\TRYFILE.csv");
int bytesRead = -1;
byte[] buffer = new byte[4096];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
} catch(Exception e) {
} finally {
outputStream.close();
inputStream.close();
}
The code works to download small sized files (i.e. 25 KB). I didn't try to download large files (on the order of 100 MB), because the files from the particular URL are always small.
I want to know what happens if I try to download larger files with this code: will it continue to work or throw an exception? Do I need to implement code (utilizing, say, setConnectTimeout or setReadTimeout) for bigger files?
Is there a url you can suggest where I can try to download large file using this code?
As suggested in the comments, create a large file yourself. To serve it over HTTP, the easiest way is probably to run Python 3 from the directory where you put the file -
python -m http.server
which will start a server on 8000. See this blog post for more details, or check out the python documentation.
Then you can test this yourself.

Pause download in Java?

I'm using this code to download a file, and I was wondering if its possible to pause the download and then resume it later, and if so how?:
URL url = new URL(URL);
URLConnection conexion = url.openConnection();
conexion.connect();
int lenghtOfFile = conexion.getContentLength();
lenghtOfFile /= 100;
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(Path + FileName);
byte data[] = new byte[1024];
long total = 0;
int count = 0;
while ((count = input.read(data)) != -1) {
output.write(data, 0, count);
total += count;
}
output.flush();
output.close();
input.close();
This is only possible if the server supports HTTP range headers (introduced in HTTP 1.1)
See this question for examples in Java: how to use the HTTP range header in J2ME?.
"Pausing" could just mean reading some of the stream and writing it to disk. When resuming you would have to use the headers to specify what is left to download.
I think the support for the resume is at the server side, the clients cannot direct it.

download doc file on android from server

hi i have a word document on server which i want to download it from android.i am using the following code
URL url = new URL(aurl[0]);
URLConnection conexion = url.openConnection();
conexion.setDoOutput(true);
conexion.setConnectTimeout(60000);
conexion.connect();
int lenghtOfFile = conexion.getContentLength();
Log.d("ANDRO_ASYNC", "Lenght of file: " + lenghtOfFile);
InputStream input = new BufferedInputStream(conexion.getInputStream());
OutputStream output = new FileOutputStream(Environment.getExternalStorageDirectory() +
"/abcd.doc");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress(""+(int)((total*100)/lenghtOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();`
when i try this code with a sample flickr link(http://farm1.static.flickr.com/114/298125983_0e4bf66782_b.jpg) it works but when i try my server url it doesnt connect.The file gets downloaded from browser though.Also can sombody tell me what is the difference between two methods openConnection() and connect() ?
Update:
It also works fine with our localhost but not on the server. In logcat I see, Request time failed: Address family not supported. Something need to be set for Doc files?
URL.openConnection(); prepares connection to be made Connect is the start of conection i think sorry if i'm wrong.
JAVADOC SAYS THESE
connect() Opens a connection to the resource. This method will not reconnect to a resource after the initial connection has been closed.
URL.openConnection() Opens a connection to the remote resource specified by this URL. This connection allows bidirectional data transfer.
hope it helped
You may need to set the content-type for word documents:
Response.ContentType = "application/ms-word";
But there are variations depending on the version.

Categories