-1

I'm trying to download file from internet using java but there have a problem. I'm not failed but each time when I'm trying to download it's downloading only 250-300 KB only though the file size is larger than that. I have tried a lot of ways but every time the result is same.

I have tried Apache Commons IO like this,

import java.io.File;
import java.net.URL;

import org.apache.commons.io.FileUtils;

public class Main {

    public static void main(String[] args) {

        try {

            String from = "https://download.gimp.org/mirror/pub/gimp/v2.8/gimp-2.8.10.tar.bz2";
            String to = "/home/ashik/gimp-2.8.10.tar.bz2";
            System.out.println("Starting!");
            FileUtils.copyURLToFile(new URL(from), new File(to), Integer.MAX_VALUE, Integer.MAX_VALUE);
            System.out.println("Finished!");
        } catch (Exception e) {

            System.err.println(e.toString());
        }
    }
}

I have tried Java NIO like this,

import java.io.FileOutputStream;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;

public class Main {

    public static void main(String[] args) {

        try {

            String from = "https://download.gimp.org/mirror/pub/gimp/v2.8/gimp-2.8.10.tar.bz2";
            String to = "/home/ashik/gimp-2.8.10.tar.bz2";
            System.out.println("Starting!");
            ReadableByteChannel rbc = Channels.newChannel(new URL(from).openStream());
            FileOutputStream fos = new FileOutputStream(to);
            fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
            fos.close();
            rbc.close();
            System.out.println("Finished!");
        } catch (Exception e) {

            System.err.println(e.toString());
        }
    }

}

I have also followed some stackoverflow solutions like, How to download and save a file from Internet using Java? , How to download large sized Files (size > 50MB) in java, etc but none of them are working.

Every time it's downloading but file size is only 250-300 KB. How to solve this problem?

Platform:

OS: Debian-9

JDK-Version: Oracle JDK-9

IDE: Eclipse Oxygen

Thank you in advance.

shmosel
  • 49,289
  • 6
  • 73
  • 138
ashikuzzaman
  • 54
  • 1
  • 6
  • In the first question you linked, one of the comments for the accepted answer says: "A single call isn't adequate. transferFrom() isnt' specified to complete the entire transfer in a single call. That's why it returns a count. You have to loop." – NAMS Nov 07 '17 at 21:39
  • Oh, then what's about 'FileUtils.copyURLToFile()' ? Why it's not working ? – ashikuzzaman Nov 08 '17 at 08:10
  • I'm not super familiar with Commons IO but as far as I can tell it's written correctly, so I don't know what's wrong with it. Are you getting an exception when you run it? – NAMS Nov 08 '17 at 15:00
  • Don’t use FileUtils and don’t use Channels. Use [Files.copy](https://docs.oracle.com/javase/9/docs/api/java/nio/file/Files.html#copy-java.io.InputStream-java.nio.file.Path-java.nio.file.CopyOption...-). – VGR Nov 09 '17 at 04:19
  • One of you are suggesting not to use FileUtils and Channels and another one is not sure that what's going on but you are doing down vote as well. Great! No, No exception has thrown. That's the main problem. It's not throwing any exception but it can't download the file. Where and how to use the loop by the way? @NAMS Can you please describe me in details? – ashikuzzaman Nov 09 '17 at 19:38

1 Answers1

0

You don’t need a third-party library to do this. You could use Channels, but it’s shorter to use Files.copy:

try (InputStream stream = new URL(from).openStream()) {
    Files.copy(stream, Paths.get(to));
}

In your case, the URL is redirecting to a different location. Ordinarily, calling setInstanceFollowRedirects would be sufficient:

HttpURLConnection conn = new URL(from).openConnection();
conn.setInstanceFollowRedirects(true);

try (InputStream stream = conn.getInputStream()) {
    Files.copy(stream, Paths.get(to));
}

However, this is a special case. Your URL is an https URL, which redirects to an http URL.

Java considers that insecure (as it should), so it will never automatically follow that redirect, even if setInstanceFollowRedirects has been called.

Which means you have to follow the redirects yourself:

URL url = new URL(from);

HttpURLConnection conn;
while (true) {
    conn = (HttpURLConnection) url.openConnection();
    conn.setInstanceFollowRedirects(true);

    int responseCode = conn.getResponseCode();
    if (responseCode != HttpURLConnection.HTTP_MOVED_PERM &&
        responseCode != HttpURLConnection.HTTP_MOVED_TEMP &&
        responseCode != 307) {

        break;
    }

    url = new URL(conn.getHeaderField("Location"));
}

try (InputStream stream = conn.getInputStream()) {
    Files.copy(stream, Paths.get(to));
}
VGR
  • 40,506
  • 4
  • 48
  • 63
  • Thank you for your reply. I tried this but the result is same. I'm attaching my code and output. Please check this. **Code:** https://gist.github.com/ashikuzzaman-ar/50a8aee9eaf86424c358c7121f52fe93 **Console:** https://drive.google.com/file/d/1E-vIKUZuAEC2uRIkKUZqqYFWW3GTFB-X/view?usp=sharing **File_Browser:** https://drive.google.com/file/d/1aDX27pQvJqdFvUoV7hDa1wDBYeSfStyr/view?usp=sharing – ashikuzzaman Nov 10 '17 at 10:33
  • Ah, I see now. The URL is doing a redirect. Updated my answer accordingly. – VGR Nov 10 '17 at 12:46
  • Yes! I also have discovered that! What was happening, every time when I was running the code, it was downloading a html file having size 250-300 KB . Thank you very much Sir. – ashikuzzaman Nov 10 '17 at 13:00
  • Can you please advice me how can I get information how much bit I have already downloaded after few seconds ? @VGR – ashikuzzaman Nov 10 '17 at 13:06
  • You’ll have to read the stream a little at a time, and do the math yourself. There is no way to do it using a single method call. There are already many Stack Overflow questions which address this. – VGR Nov 10 '17 at 14:59
  • Oh Thank you very much. I discovered an alternative way for doing this in a single line by adding `Files.size(Paths.get(to))` . Full source is here: https://gist.github.com/ashikuzzaman-ar/59952f64ccf361e71b1c21bcea7d813c – ashikuzzaman Nov 10 '17 at 21:06