Home > Back-end >  Why is it that Java NIO Download works on Windows but returns Forbidden 403 on macOS?
Why is it that Java NIO Download works on Windows but returns Forbidden 403 on macOS?

Time:07-08

I have a small command-line program that I wrote for re-downloading files from a server in bulk. It works flawlessly in Windows, but doesn't seem to work in macOS.

Here is the error I receive:

Download failed: java.io.IOException: Server returned HTTP response code: 403 for URL:
https://cdn.modrinth.com/data/P7dR8mSH/versions/0.56.3 1.19/fabric-api-0.56.3+1.19.jar
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1914)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1512)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:268)
    at java.net.URL.openStream(URL.java:1092)
    at main.downloadUsingNIO(main.java:37)
    at main.main(main.java:20)

Relevant code:

   private static void downloadUsingNIO(String urlStr, String file) throws IOException {
       URL url = new URL(urlStr);
       ReadableByteChannel rbc = Channels.newChannel(url.openStream());
       FileOutputStream fos = new FileOutputStream(file);
       fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
       fos.close();
       rbc.close();
   }

Usage:

downloadUsingNIO(URLOFFILE, WHERETOSAVEANDTOWHATFILE);

Other information:

  1. Both windows and macos accounts used are the primary administrator accounts.
  2. running the jar with elevated permissions through "sudo java -jar " does not fix it.
  3. The file is downloadable in safari with the same link.
  4. The download works with "curl -o thing.jar "
  5. Tried Apache Commons.IO, didn't do anything as it uses the same code underneath (the stacktrace was the same)

Thank you for the answers, this is the code that I used to fix the issue:

private static void downloadUsingNIO(String Strurl, String path) throws IOException {

        final URLConnection connection = new URL(Strurl).openConnection();
        connection.addRequestProperty("User-Agent",
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Firefox/102.0");

        final int contentLength = connection.getContentLength();
        final File end = new File(path);

        if (end.exists()) {
            final URLConnection savedFileConnection = end.toURI().toURL().openConnection();
            if (savedFileConnection.getContentLength() == contentLength) {
                return;
            }
        } else {
            final File dir = end.getParentFile();
            if (!dir.exists())
                dir.mkdirs();
        }

        final ReadableByteChannel rbc = Channels.newChannel(connection.getInputStream());
        final FileOutputStream fos = new FileOutputStream(end);
        fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
        fos.close();
        
        return;
    }

CodePudding user response:

With high probably, the HTTP server doesn't like the Java default user agent header, which is being sent - or it's absence; use another client. This can easily be validated by comparing the server logs. https://datatracker.ietf.org/doc/html/rfc7231#section-6.5.3

The point is, that neither NIO Channel nor URL permit setting that header.

  • Related