Last active
December 5, 2018 02:07
-
-
Save Skarlit/a5dea8b9836ee74c41c791dc193523e0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
final long MAX_ALLOWED_CHUNK_SIZE = 15 * 1024 * 1024; | |
final Pattern rangeMatcher = Pattern.compile("[^\\d]+(\\d+)[^\\d]+(\\d+)?"); | |
public Result download(String path) { | |
String sanitizedPath; | |
try { | |
sanitizedPath = sanitizedUserInputPath(path == null ? "" : path); | |
} catch(RuntimeException e) { | |
return badRequest(e.toString()); | |
} | |
if (!request().getHeaders().contains("Range")) { | |
return ok(new java.io.File(sanitizedPath)); | |
} | |
String rangeHeader = request().getHeaders().get("Range").get(); | |
Matcher rangeValues = rangeMatcher.matcher(rangeHeader); | |
if (!rangeValues.find()) { | |
return badRequest("Missing range header"); | |
} | |
long fileSize = new File(sanitizedPath).length(); | |
long start, end; | |
if (rangeValues.group(1) != null) { | |
start = Long.parseLong(rangeValues.group(1)); | |
} else { | |
start = 0; | |
} | |
if (rangeValues.group(2) != null) { | |
// -1 because byte array index starts at 0. | |
end = Math.min(Long.parseLong(rangeValues.group(2)), MAX_ALLOWED_CHUNK_SIZE - 1); | |
} else { | |
end = Math.min(fileSize - 1, start + MAX_ALLOWED_CHUNK_SIZE - 1); | |
} | |
// get MIME type | |
String mimeType; | |
try { | |
mimeType = Files.probeContentType(Paths.get(sanitizedPath)); | |
} catch (IOException e) { | |
return badRequest("Unknown MIME type"); | |
} | |
long contentLength = end - start + 1; | |
String returnContentRange = String.format("bytes %d-%d/%d", start, end, fileSize); | |
Source<ByteString, ?> source = FileIO.fromPath(Paths.get(sanitizedPath), (int) contentLength, start); | |
return new Result( | |
new ResponseHeader(206, ImmutableMap.of( | |
"Accept-Ranges", "bytes", | |
"Content-Range", returnContentRange // Without this field, it won't work | |
)), | |
new HttpEntity.Streamed(source, Optional.of(contentLength), Optional.of(mimeType)) | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment