|
import de.schlichtherle.truezip.rof.AbstractReadOnlyFile; |
|
import de.schlichtherle.truezip.zip.ZipEntry; |
|
import de.schlichtherle.truezip.zip.ZipFile; |
|
|
|
// ... |
|
|
|
@RequestMapping(value = "/Repository/unzip/copy/{copyId:nla\\.obj-[^/]+}/{path:.+}", method = {RequestMethod.GET}) |
|
@ResponseBody |
|
public void unzipCopy(@PathVariable String copyId, |
|
@PathVariable String path, |
|
HttpServletResponse response) throws IOException { |
|
try (AmberSession session = amberDbService.get()) { |
|
Copy copy = session.findModelObjectById(copyId, Copy.class); |
|
try (SeekableByteChannel channel = copy.getFile().openChannel(); |
|
ZipFile zip = new ZipFile(new ChannelReadOnlyFile(channel))) { |
|
ZipEntry entry = zip.getEntry(path); |
|
|
|
response.addHeader("Content-Length", Long.toString(entry.getSize())); |
|
|
|
// XXX; check that this map has the right content type mappings for your epub stuff |
|
String contentType = MimetypesFileTypeMap.getDefaultFileTypeMap().getContentType(path); |
|
response.setContentType(contentType); |
|
|
|
IOUtils.copy(zip.getInputStream(entry), response.getOutputStream()); |
|
} |
|
} |
|
} |
|
|
|
static class ChannelReadOnlyFile extends AbstractReadOnlyFile { |
|
final SeekableByteChannel channel; |
|
|
|
ChannelReadOnlyFile(SeekableByteChannel channel) { |
|
this.channel = channel; |
|
} |
|
|
|
@Override |
|
public long length() throws IOException { |
|
return channel.size(); |
|
} |
|
|
|
@Override |
|
public long getFilePointer() throws IOException { |
|
return channel.position(); |
|
} |
|
|
|
@Override |
|
public void seek(long position) throws IOException { |
|
channel.position(position); |
|
} |
|
|
|
@Override |
|
public int read() throws IOException { |
|
ByteBuffer buf = ByteBuffer.allocate(1); |
|
int nread = channel.read(buf); |
|
return nread > 0 ? buf.get(0) : nread; |
|
} |
|
|
|
@Override |
|
public int read(byte[] bytes, int off, int len) throws IOException { |
|
ByteBuffer buf = ByteBuffer.wrap(bytes, off, len); |
|
return channel.read(buf); |
|
} |
|
|
|
|
|
@Override |
|
public void close() throws IOException { |
|
channel.close(); |
|
} |
|
} |