static void downloadWebp(String url) {
URL url1;
try {
url1 = new URL(url);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
{
// download webp
ReadableByteChannel readableByteChannel;
try {
readableByteChannel = Channels.newChannel(url1.openStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
Path path = Paths.get(System.getProperty("user.home"), "image", Paths.get(url1.getPath()).getFileName().toString() + 1);
try (FileOutputStream fileOutputStream = new FileOutputStream(path.toAbsolutePath().toString())) {
fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
} catch (IOException e) {
throw new RuntimeException(e);
}
// Can I check if download file's length matches the content-length header ?
}
}
Call like
downloadWebp("https://cdn.discordapp.com/attachments/1098794840742961242/1100590092957003877/Jeffery_cherry_blossoms_blooming_in_the_rain_by_Yoko_Ishii_wate_8a2f060e-32dc-4567-a3df-8bfdbb56adfd.webp");
As In previous java code, I had download a image, how can I double check if downloaded file's length matches the content-length header's value ?
As I found some file not really fully downloaded after fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
returns, I have to retry in that case.
Try this:
public static void main(String[] args) throws Exception {
downloadWebp(
Files.createTempFile("sprites", "svg"),
URI.create("https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27"),
null // new Proxy(Proxy.Type.HTTP, new InetSocketAddress("<proxy-host-if-used>", 8080))
);
}
private static void downloadWebp(Path path, URI uri, Proxy proxy) throws Exception {
HttpURLConnection connection = (HttpURLConnection) (proxy == null
? uri.toURL().openConnection() : uri.toURL().openConnection(proxy));
try {
//connection.setConnectTimeout(30_000);
//connection.setReadTimeout(30_000);
connection.connect();
try (
ReadableByteChannel readableByteChannel = Channels.newChannel(connection.getInputStream());
FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.WRITE)
) {
int length = connection.getHeaderFieldInt("Content-Length", -1);
System.out.println("Content-Length: " + length);
while (length > 0) {
long written = fileChannel.transferFrom(readableByteChannel, 0, length /*Math.min(length, 2048)*/);
length -= written;
System.out.println("written: " + written);
}
}
} finally {
connection.disconnect();
}
}
You will get both content-length
and actually transferred bytes:
Content-Length: 7542
written: 7542
As @user207421 mentioned in comments it's true, you need to use transferFrom
in a loop.