Class FileDownloadUtils
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic enumWhat to do with theETagresponse header when no explicit hash URL is available.static enum -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic voidcheckHttpStatus(URLConnection connection) Verifies that an HTTP connection returned a 2xx status.static StringcomputeHash(File file, FileDownloadUtils.Hash hash) Computes the digest of a file.static StringcomputeHash(InputStream in, FileDownloadUtils.Hash hash) Computes the digest of a stream.static voidcreateValidationFiles(URLConnection resourceUrlConnection, File localDestination, URL hashURL, FileDownloadUtils.Hash hash) Creates validation files beside a file to be downloaded.
Whenever possible, for afile.extfile, it createsfile.ext.sizeandfile.hash_XXXXin the same folder wherefile.extexists (XXXX may be DM5, SHA1, or SHA256).static voidcreateValidationFiles(URLConnection resourceUrlConnection, File localDestination, URL hashURL, FileDownloadUtils.Hash hash, FileDownloadUtils.ETagPolicy eTagPolicy) Creates validation files beside a file to be downloaded, with explicit control over how theETagresponse header is treated.static voidcreateValidationFiles(URL url, File localDestination, URL hashURL, FileDownloadUtils.Hash hash) Creates validation files beside a file to be downloaded.
Whenever possible, for afile.extfile, it createsfile.ext.sizeandfile.hashfor in the same folder wherefile.extexists.static voidcreateValidationFiles(URL url, File localDestination, URL hashURL, FileDownloadUtils.Hash hash, FileDownloadUtils.ETagPolicy eTagPolicy) Creates validation files beside a file to be downloaded, with explicit control over how theETagresponse header is treated.static voiddeleteDirectory(String dir) Recursively delete a folder & contentsstatic voiddeleteDirectory(Path dir) Recursively delete a folder & contentsstatic voiddownloadFile(URL url, File destination) Download the content provided at URL url and store the result to a local file, using a temp file to cache the content in case something goes wrong in download.static voiddownloadFileWithValidation(URL url, File destination, URL hashURL, FileDownloadUtils.Hash hash, FileDownloadUtils.ETagPolicy eTagPolicy) Downloads a file and writes its validation metadata in a single pass over a single connection.static StringexpandUserHome(String file) Expands ~ in paths to the user's home directory.static StringThe JDK name of a hashing algorithm, which differs from the enum constant for the SHA variants.static StringGets the file extension of a file, excluding '.'.static StringGets the file name up to and excluding the first '.' character.static FileDownloadUtils.HashhashFromETag(String eTagHeaderValue) Determines which hashing algorithm anETagheader value represents, based on the length of the hex digest it contains.static StringnormalizeETag(String eTagHeaderValue) Strips the weak-validator prefix and surrounding quotes from anETagheader value.static URLConnectionopenConnectionFollowingRedirects(URL url, int timeout) Opens a connection, following any redirect thatHttpURLConnectiondeclines to follow itself.static booleanPings a HTTP URL.static URLConnectionprepareURLConnection(String url, int timeout) PrepareURLConnectionwith customised timeouts.static StringtoUnixPath(String path) Converts path to Unix convention and adds a terminating slash if it was omitted.static booleanvalidateFile(File localFile) Validate a local file based on pre-existing metadata files for size and hash.
If the passed inlocalFileparameter is a file namedfile.ext, the function searches in the same folder for:file.ext.size: If found, it compares the size stored in it to the length oflocalFile(in bytes).file.ext.hash_XXXX (where XXXX is DM5, SHA1, or SHA256): If found, it compares the size stored in it to the hash code oflocalFile. If any of these comparisons fail, the function returnsfalse. otherwise it returns true.static booleanverifyHash(File file, FileDownloadUtils.Hash hash, String expectedHex) Checks a file against an expected digest.static voidwriteHashFile(File localDestination, FileDownloadUtils.Hash hash, String hexDigest) Writes a<name>.hash_<ALGORITHM>sidecar file containing the given digest as bare lowercase hex.
-
Constructor Details
-
FileDownloadUtils
public FileDownloadUtils()
-
-
Method Details
-
getFileExtension
Gets the file extension of a file, excluding '.'. If the file name has no extension the file name is returned.- Parameters:
f- a File- Returns:
- The extension
-
getFilePrefix
Gets the file name up to and excluding the first '.' character. If there is no extension, the full filename is returned.- Parameters:
f- A file- Returns:
- A possibly empty but non-null String.
-
downloadFile
Download the content provided at URL url and store the result to a local file, using a temp file to cache the content in case something goes wrong in download. A timeout of 60 seconds is hard-coded and 10 retries are attempted.- Parameters:
url-destination-- Throws:
IOException
-
downloadFileWithValidation
public static void downloadFileWithValidation(URL url, File destination, URL hashURL, FileDownloadUtils.Hash hash, FileDownloadUtils.ETagPolicy eTagPolicy) throws IOException Downloads a file and writes its validation metadata in a single pass over a single connection.This is preferable to calling
createValidationFiles(URL, File, URL, Hash)followed bydownloadFile(URL, File): those open separate connections, so theContent-Lengthrecorded in the.sizefile comes from a different response than the bytes actually written. If the resource changes between the two requests, the cache entry is left permanently failing validation.The content is streamed to a temporary file and only moved into place once the declared length and (where available) the checksum have been confirmed, so a failed download never leaves a partial file at
destination.- Parameters:
url- the remote file to downloaddestination- the local file to download into. Its parent directory must exist.hashURL- URL of a file containing the expected hash. May benull.hash- the hashing algorithm matchinghashURL. Ignored whenhashURLisnull.eTagPolicy- what to do with anETagresponse header whenhashURLisnull. May benull, which is treated asFileDownloadUtils.ETagPolicy.IGNORE.- Throws:
HttpStatusException- if the server answered with a non-2xx statusIOException- if the transfer failed, or the transferred content did not match the length or checksum the server declared- Since:
- 7.3.0
-
openConnectionFollowingRedirects
public static URLConnection openConnectionFollowingRedirects(URL url, int timeout) throws IOException Opens a connection, following any redirect thatHttpURLConnectiondeclines to follow itself.The JDK follows 301, 302 and 303 within a protocol, but it never follows 307 or 308, and it never follows a redirect that changes http to https. Both gaps have broken downloads in practice: CATH began answering http with a 301 to https, and ECOD now answers with a 308 to a rewritten path. A browser follows either without comment, so a service making that change has no reason to expect it to break us.
A redirect from https to http is deliberately not followed: a redirect must never silently downgrade the transport. Such a response is returned as it is, for
checkHttpStatus(URLConnection)to reject.- Parameters:
url- the URL to opentimeout- connect and read timeout, in milliseconds- Returns:
- a connected
URLConnectionat the final location - Throws:
HttpStatusException- if the redirects loop or exceed the limitIOException- if the connection could not be opened- Since:
- 7.3.0
-
checkHttpStatus
Verifies that an HTTP connection returned a 2xx status. Connections using a non-HTTP protocol (file:,ftp:, ...) are left alone.Without this check a 404 error page is written into the cache as though it were the requested file — and because the
.sizesidecar is then taken from that same error response,validateFile(File)would subsequently declare it valid.- Parameters:
connection- an already connectedURLConnection- Throws:
HttpStatusException- if the status is outside the 2xx rangeIOException- if the status could not be read- Since:
- 7.3.0
-
createValidationFiles
public static void createValidationFiles(URL url, File localDestination, URL hashURL, FileDownloadUtils.Hash hash) Creates validation files beside a file to be downloaded.
Whenever possible, for afile.extfile, it createsfile.ext.sizeandfile.hashfor in the same folder wherefile.extexists. If the file connection size could not be deduced from the URL, no size file is created. IfhashURLisnull, no hash file is created.- Parameters:
url- the remote file URL to downloadlocalDestination- the local file to download intohashURL- the URL of the hash file to download. Can benull.hash- The Hashing algorithm. Ignored ifhashURLisnull.
-
createValidationFiles
public static void createValidationFiles(URL url, File localDestination, URL hashURL, FileDownloadUtils.Hash hash, FileDownloadUtils.ETagPolicy eTagPolicy) Creates validation files beside a file to be downloaded, with explicit control over how theETagresponse header is treated.- Parameters:
url- the remote file URL to downloadlocalDestination- the local file to download intohashURL- the URL of the hash file to download. Can benull.hash- The Hashing algorithm. Ignored ifhashURLisnull.eTagPolicy- how to treat theETagheader whenhashURLisnull. May benull, treated asFileDownloadUtils.ETagPolicy.IGNORE.- Since:
- 7.3.0
-
createValidationFiles
public static void createValidationFiles(URLConnection resourceUrlConnection, File localDestination, URL hashURL, FileDownloadUtils.Hash hash) Creates validation files beside a file to be downloaded.
Whenever possible, for afile.extfile, it createsfile.ext.sizeandfile.hash_XXXXin the same folder wherefile.extexists (XXXX may be DM5, SHA1, or SHA256). If the file connection size could not be deduced from the resourceUrlConnectionURLConnection, no size file is created. IfhashURLisnull, no hash file is created.
N.B. None of the hashing algorithms is implemented (yet), because we did not need any of them yet.- Parameters:
resourceUrlConnection- the remote file URLConnection to downloadlocalDestination- the local file to download intohashURL- the URL of the hash file to download. Can benull.hash- The Hashing algorithm. Ignored ifhashURLisnull.- Since:
- 7.0.0
-
createValidationFiles
public static void createValidationFiles(URLConnection resourceUrlConnection, File localDestination, URL hashURL, FileDownloadUtils.Hash hash, FileDownloadUtils.ETagPolicy eTagPolicy) Creates validation files beside a file to be downloaded, with explicit control over how theETagresponse header is treated.Nothing is written when the connection reports a non-2xx status: previously an error page's
Content-Lengthwould be recorded as the expected size, so the cached error page then passed validation.- Parameters:
resourceUrlConnection- the remote file URLConnection to downloadlocalDestination- the local file to download intohashURL- the URL of the hash file to download. Can benull.hash- The Hashing algorithm. Ignored ifhashURLisnull.eTagPolicy- how to treat theETagheader whenhashURLisnull. May benull, treated asFileDownloadUtils.ETagPolicy.IGNORE.- Since:
- 7.3.0
-
hashFromETag
Determines which hashing algorithm anETagheader value represents, based on the length of the hex digest it contains.Only a value consisting solely of hex characters is considered. The
<time>-<size>form used by nginx and Apache always contains a-and therefore never matches.- Parameters:
eTagHeaderValue- the raw header value, possibly quoted or weak-prefixed. May benull.- Returns:
- the matching algorithm, or
FileDownloadUtils.Hash.UNKNOWNif the value is not a hex digest of a recognised length - Since:
- 7.3.0
-
normalizeETag
Strips the weak-validator prefix and surrounding quotes from anETagheader value.- Parameters:
eTagHeaderValue- the raw header value. May benull.- Returns:
- the bare value, or
nullif the input wasnullor blank - Since:
- 7.3.0
-
writeHashFile
public static void writeHashFile(File localDestination, FileDownloadUtils.Hash hash, String hexDigest) Writes a<name>.hash_<ALGORITHM>sidecar file containing the given digest as bare lowercase hex.- Parameters:
localDestination- the file the digest describeshash- the hashing algorithmhexDigest- the digest, in hex- Since:
- 7.3.0
-
computeHash
Computes the digest of a file.- Parameters:
file- the file to digesthash- the algorithm to use- Returns:
- the digest as bare lowercase hex
- Throws:
IOException- if the file could not be read- Since:
- 7.3.0
-
computeHash
Computes the digest of a stream. The stream is read to its end but not closed.- Parameters:
in- the stream to digesthash- the algorithm to use- Returns:
- the digest as bare lowercase hex
- Throws:
IOException- if the stream could not be read- Since:
- 7.3.0
-
verifyHash
public static boolean verifyHash(File file, FileDownloadUtils.Hash hash, String expectedHex) throws IOException Checks a file against an expected digest.- Parameters:
file- the file to checkhash- the algorithm to useexpectedHex- the expected digest, in hex; compared case-insensitively- Returns:
trueif the digests match- Throws:
IOException- if the file could not be read- Since:
- 7.3.0
-
getAlgorithmName
The JDK name of a hashing algorithm, which differs from the enum constant for the SHA variants.- Parameters:
hash- the algorithm- Returns:
- the name to pass to
MessageDigest.getInstance(String) - Since:
- 7.3.0
-
validateFile
Validate a local file based on pre-existing metadata files for size and hash.
If the passed inlocalFileparameter is a file namedfile.ext, the function searches in the same folder for:file.ext.size: If found, it compares the size stored in it to the length oflocalFile(in bytes).file.ext.hash_XXXX (where XXXX is DM5, SHA1, or SHA256): If found, it compares the size stored in it to the hash code oflocalFile.
false. otherwise it returns true.N.B. None of the 3 common verification hashing algorithms are implement yet.
- Parameters:
localFile- The file to validate- Returns:
falseif any of the size or hash code metadata files exists but its contents does not match the expected value in the file,trueotherwise.- Since:
- 7.0.0
-
toUnixPath
Converts path to Unix convention and adds a terminating slash if it was omitted.- Parameters:
path- original platform dependent path- Returns:
- path in Unix convention
- Since:
- 3.2
-
expandUserHome
Expands ~ in paths to the user's home directory.This does not work for some special cases for paths: Other users' homes (~user/...), and Tilde expansion within the path (/.../~/...). In these cases the original argument is returned.
- Parameters:
file- A filepath starting with a tilde- Returns:
- An absolute path
-
ping
Pings a HTTP URL. This effectively sends a HEAD request and returnstrueif the response code is in the 200-399 range.- Parameters:
url- The HTTP URL to be pinged.timeout- The timeout in millis for both the connection timeout and the response read timeout. Note that the total timeout is effectively two times the given timeout.- Returns:
trueif the given HTTP URL has returned response code 200-399 on a HEAD request within the given timeout, otherwisefalse.
-
prepareURLConnection
PrepareURLConnectionwith customised timeouts.- Parameters:
url- The URLtimeout- The timeout in millis for both the connection timeout and the response read timeout. Note that the total timeout is effectively two times the given timeout.Example of code.
UrlConnection conn = prepareURLConnection("http://www.google.com/", 20000); conn.connect(); conn.getInputStream();NB. User should execute connect() method before getting input stream.
- Returns:
- Throws:
IOException
-
deleteDirectory
Recursively delete a folder & contents- Parameters:
dir- directory to delete- Throws:
IOException
-
deleteDirectory
Recursively delete a folder & contents- Parameters:
dir- directory to delete- Throws:
IOException
-