|
|
|
@@ -3,6 +3,7 @@ package sh.rhiobet.lalafin.file;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.net.URLDecoder;
|
|
|
|
import java.net.URLDecoder;
|
|
|
|
|
|
|
|
import java.net.URLEncoder;
|
|
|
|
import java.nio.channels.Channels;
|
|
|
|
import java.nio.channels.Channels;
|
|
|
|
import java.nio.channels.FileChannel;
|
|
|
|
import java.nio.channels.FileChannel;
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
|
@@ -73,8 +74,9 @@ public class FileServeService {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
response = Response.ok(path.toFile());
|
|
|
|
response = Response.ok(path.toFile());
|
|
|
|
|
|
|
|
channel.position(rangeStart);
|
|
|
|
response.entity(new FileServeInputStream(Channels.newInputStream(channel),
|
|
|
|
response.entity(new FileServeInputStream(Channels.newInputStream(channel),
|
|
|
|
rangeStart, rangeEnd));
|
|
|
|
rangeEnd + 1 - rangeStart));
|
|
|
|
|
|
|
|
|
|
|
|
response.header("Content-Length",
|
|
|
|
response.header("Content-Length",
|
|
|
|
Long.toString(rangeEnd + 1 - rangeStart));
|
|
|
|
Long.toString(rangeEnd + 1 - rangeStart));
|
|
|
|
@@ -87,8 +89,8 @@ public class FileServeService {
|
|
|
|
channel.close();
|
|
|
|
channel.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
response.header("Accept-Ranges", "bytes");
|
|
|
|
response.header("Accept-Ranges", "bytes");
|
|
|
|
response.header("Content-Disposition",
|
|
|
|
response.header("Content-Disposition", "inline; filename*=UTF-8''" +
|
|
|
|
"inline; filename=\"" + fileInfo.filename + "\"");
|
|
|
|
URLEncoder.encode(fileInfo.filename, StandardCharsets.UTF_8).replace("+", "%20"));
|
|
|
|
response.header("Content-Type", FileHelper.getMimeType(fileInfo.filename));
|
|
|
|
response.header("Content-Type", FileHelper.getMimeType(fileInfo.filename));
|
|
|
|
if (path.toString().contains("/.thumbnails/")) {
|
|
|
|
if (path.toString().contains("/.thumbnails/")) {
|
|
|
|
response.header("Cache-Control", "max-age=604800");
|
|
|
|
response.header("Cache-Control", "max-age=604800");
|
|
|
|
@@ -110,17 +112,19 @@ public class FileServeService {
|
|
|
|
ZipEntry zipEntry = zipFile.getEntry(name);
|
|
|
|
ZipEntry zipEntry = zipFile.getEntry(name);
|
|
|
|
|
|
|
|
|
|
|
|
if (zipEntry == null) {
|
|
|
|
if (zipEntry == null) {
|
|
|
|
|
|
|
|
zipFile.close();
|
|
|
|
throw new IOException();
|
|
|
|
throw new IOException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ResponseBuilder response;
|
|
|
|
ResponseBuilder response;
|
|
|
|
long fileSize = zipEntry.getSize();
|
|
|
|
long fileSize = zipEntry.getSize();
|
|
|
|
|
|
|
|
|
|
|
|
response = Response.ok(zipFile.getInputStream(zipEntry));
|
|
|
|
response = Response.ok(new ZipEntryInputStream(zipFile, zipFile.getInputStream(zipEntry)));
|
|
|
|
response.header("Content-Length", Long.toString(fileSize));
|
|
|
|
response.header("Content-Length", Long.toString(fileSize));
|
|
|
|
|
|
|
|
|
|
|
|
response.header("Accept-Ranges", "bytes");
|
|
|
|
response.header("Accept-Ranges", "bytes");
|
|
|
|
response.header("Content-Disposition", "inline; filename=\"" + name + "\"");
|
|
|
|
response.header("Content-Disposition", "inline; filename*=UTF-8''" +
|
|
|
|
|
|
|
|
URLEncoder.encode(name, StandardCharsets.UTF_8).replace("+", "%20"));
|
|
|
|
response.header("Content-Type", FileHelper.getMimeType(name));
|
|
|
|
response.header("Content-Type", FileHelper.getMimeType(name));
|
|
|
|
return response.build();
|
|
|
|
return response.build();
|
|
|
|
} catch (IOException e) {
|
|
|
|
} catch (IOException e) {
|
|
|
|
@@ -133,22 +137,14 @@ class FileServeInputStream extends InputStream {
|
|
|
|
private InputStream is;
|
|
|
|
private InputStream is;
|
|
|
|
private long remaining;
|
|
|
|
private long remaining;
|
|
|
|
|
|
|
|
|
|
|
|
public FileServeInputStream(InputStream is, long startRange, long endRange) throws IOException {
|
|
|
|
public FileServeInputStream(InputStream is, long remaining) throws IOException {
|
|
|
|
this.is = is;
|
|
|
|
this.is = is;
|
|
|
|
try {
|
|
|
|
this.remaining = remaining;
|
|
|
|
this.is.skip(startRange);
|
|
|
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
this.is.close();
|
|
|
|
|
|
|
|
} catch (Exception ignored) {}
|
|
|
|
|
|
|
|
throw e;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
this.remaining = endRange + 1 - startRange;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public int available() throws IOException {
|
|
|
|
public int available() throws IOException {
|
|
|
|
return this.is.available();
|
|
|
|
return (int) Math.min(this.is.available(), this.remaining);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
@@ -170,27 +166,37 @@ class FileServeInputStream extends InputStream {
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public byte[] readAllBytes() throws IOException {
|
|
|
|
public byte[] readAllBytes() throws IOException {
|
|
|
|
return this.is.readAllBytes();
|
|
|
|
byte[] bytes = this.is.readNBytes((int) this.remaining);
|
|
|
|
|
|
|
|
this.remaining -= bytes.length;
|
|
|
|
|
|
|
|
return bytes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public byte[] readNBytes(int arg0) throws IOException {
|
|
|
|
public byte[] readNBytes(int len) throws IOException {
|
|
|
|
return this.is.readNBytes(arg0);
|
|
|
|
byte[] bytes = this.is.readNBytes((int) Math.min(len, this.remaining));
|
|
|
|
|
|
|
|
this.remaining -= bytes.length;
|
|
|
|
|
|
|
|
return bytes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public int readNBytes(byte[] arg0, int arg1, int arg2) throws IOException {
|
|
|
|
public int readNBytes(byte[] buf, int off, int len) throws IOException {
|
|
|
|
return this.is.readNBytes(arg0, arg1, arg2);
|
|
|
|
int read = this.is.readNBytes(buf, off, (int) Math.min(len, this.remaining));
|
|
|
|
|
|
|
|
this.remaining -= read;
|
|
|
|
|
|
|
|
return read;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public long skip(long arg0) throws IOException {
|
|
|
|
public long skip(long n) throws IOException {
|
|
|
|
return this.is.skip(arg0);
|
|
|
|
long skipped = this.is.skip(Math.min(n, this.remaining));
|
|
|
|
|
|
|
|
this.remaining -= skipped;
|
|
|
|
|
|
|
|
return skipped;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void skipNBytes(long arg0) throws IOException {
|
|
|
|
public void skipNBytes(long n) throws IOException {
|
|
|
|
this.is.skipNBytes(arg0);
|
|
|
|
long toSkip = Math.min(n, this.remaining);
|
|
|
|
|
|
|
|
this.is.skipNBytes(toSkip);
|
|
|
|
|
|
|
|
this.remaining -= toSkip;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
@@ -216,3 +222,62 @@ class FileServeInputStream extends InputStream {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ZipEntryInputStream extends InputStream {
|
|
|
|
|
|
|
|
private final ZipFile zipFile;
|
|
|
|
|
|
|
|
private final InputStream is;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public ZipEntryInputStream(ZipFile zipFile, InputStream is) {
|
|
|
|
|
|
|
|
this.zipFile = zipFile;
|
|
|
|
|
|
|
|
this.is = is;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public int read() throws IOException {
|
|
|
|
|
|
|
|
return this.is.read();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public int read(byte[] buffer) throws IOException {
|
|
|
|
|
|
|
|
return this.is.read(buffer);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public int read(byte[] buffer, int off, int len) throws IOException {
|
|
|
|
|
|
|
|
return this.is.read(buffer, off, len);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public byte[] readAllBytes() throws IOException {
|
|
|
|
|
|
|
|
return this.is.readAllBytes();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public byte[] readNBytes(int len) throws IOException {
|
|
|
|
|
|
|
|
return this.is.readNBytes(len);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public int readNBytes(byte[] buf, int off, int len) throws IOException {
|
|
|
|
|
|
|
|
return this.is.readNBytes(buf, off, len);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public long skip(long n) throws IOException {
|
|
|
|
|
|
|
|
return this.is.skip(n);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public int available() throws IOException {
|
|
|
|
|
|
|
|
return this.is.available();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public void close() throws IOException {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
this.is.close();
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
|
|
this.zipFile.close();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|