}
String inode = null;
IFileAsset file = null;
Identifier identifier = null;
boolean canRead = false;
if(UtilMethods.isSet(relativePath) && relativePath.contains("fileAsset")){
String[] splits = relativePath.split(Pattern.quote(File.separator));
if(splits.length>0){
inode = splits[3];
Contentlet cont = null;
try{
cont = APILocator.getContentletAPI().find(inode, user, true);
file = APILocator.getFileAssetAPI().fromContentlet(cont);
identifier = APILocator.getIdentifierAPI().find(cont);
canRead = true;
}catch(Exception e){
Logger.warn(this, "Unable to find file asset contentlet with inode " + inode, e);
}
}
}else if(UtilMethods.isSet(uri) && uri.contains("fileAsset")){
String[] splits = uri.split(Pattern.quote(File.separator));
if(splits.length>0){
inode = splits[3];
Contentlet cont = null;
try{
cont = APILocator.getContentletAPI().find(inode, user, true);
file = APILocator.getFileAssetAPI().fromContentlet(cont);
identifier = APILocator.getIdentifierAPI().find(cont);
canRead = true;
}catch(Exception e){
Logger.warn(this, "Unable to find file asset contentlet with inode " + inode, e);
}
}
}else{
inode = UtilMethods.getFileName(f.getName());
file = APILocator.getFileAPI().find(inode, user, true);
identifier = APILocator.getIdentifierAPI().find((com.dotmarketing.portlets.files.model.File)file);
com.dotmarketing.portlets.files.model.File fProxy = new com.dotmarketing.portlets.files.model.File();
fProxy.setIdentifier(identifier.getInode());
canRead = permissionAPI.doesUserHavePermission(fProxy, PERMISSION_READ, user, true);
}
// Identifier identifier = APILocator.getIdentifierAPI().findFromInode(Long.parseLong(inode));
String mimeType = APILocator.getFileAPI().getMimeType(f.getName());
if (mimeType == null)
mimeType = "application/octet-stream";
response.setContentType(mimeType);
//Checking permissions
/**
* Build a fake proxy file object so we
* can get inheritable permissions on it
* without having to hit cache or db
*/
if (!canRead) {
if(user == null){
request.getSession(true).setAttribute(com.dotmarketing.util.WebKeys.REDIRECT_AFTER_LOGIN, request.getRequestURI());//DOTCMS-5682
//Sending user to unauthorized the might send him to login
response.sendError(401, "The requested file is unauthorized");
}else{
//sending the user to forbidden
response.sendError(403, "The requested file is forbidden");
}
return;
}
response.setHeader("Content-Disposition","filename=\"" + file.getFileName() + "\"");
/*
* Setting the proper content headers
*/
if(request.getParameter("dotcms_force_download") != null || request.getParameter("force_download") != null) {
String url = request.getRequestURL().toString();
String filename = url.substring(url.lastIndexOf("/") + 1, url.length());
filename = file.getFileName();
response.setHeader("Content-Type", "application/force-download");
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
} else {
boolean _adminMode = false;
try {
_adminMode = (session!=null && session.getAttribute(com.dotmarketing.util.WebKeys.ADMIN_MODE_SESSION) != null);
}catch(Exception e){
}
// Set the expiration time
if (!_adminMode) {
if(!DownloadUtil.isModifiedEtag(request, response, inode, f.lastModified(), f.length())) {
return;
}
/* if we are in ADMIN MODE, don't cache */
}else{
GregorianCalendar expiration = new GregorianCalendar();
expiration.add(java.util.Calendar.MONTH, -1);
response.setHeader("Expires", DownloadUtil.httpDate.get().format(expiration.getTime()));
response.setHeader("Cache-Control", "max-age=-1");
}
}
ServletOutputStream out = null;
FileChannel from = null;
WritableByteChannel to = null;
RandomAccessFile input = null;
try {
out = response.getOutputStream();
from = new FileInputStream(f).getChannel();
to = Channels.newChannel(out);
//DOTCMS-5716
//32 MB at a time
int maxTransferSize = (32 * 1024 * 1024) ;
long size = from.size();
long position = 0;
boolean responseSent = false;
byte[] data = Files.toByteArray(f);
//ServletOutputStream sos = response.getOutputStream();
//extract range header
String rangeHeader = request.getHeader("range");
if(UtilMethods.isSet(rangeHeader)){
response.setHeader("Accept-Ranges", "bytes");
// Range header should match format "bytes=n-n,n-n,n-n...". If not, then return 416.
if (!rangeHeader.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) {
response.setHeader("Content-Range", "bytes */" + data.length); // Required in 416.
response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
return;
}
//parse multiple range bytes
ArrayList<SpeedyAssetServletUtil.ByteRange> ranges = SpeedyAssetServletUtil.parseRange(rangeHeader, data.length);
if (ranges != null){
SpeedyAssetServletUtil.ByteRange full = new SpeedyAssetServletUtil.ByteRange(0, f.length() - 1, f.length());
if (ranges.isEmpty() || ranges.get(0).equals(full)) {
// Return full file.
input = new RandomAccessFile(f, "r");
SpeedyAssetServletUtil.ByteRange r = full;
response.setContentType(file.getMimeType());
response.setHeader("Content-Range", "bytes " + r.start + "-" + r.end + "/" + r.total);
response.setHeader("Content-Length", String.valueOf(r.length));
// Copy full range.
SpeedyAssetServletUtil.copy(input, out, r.start, r.length);
} else if (ranges.size() == 1){
SpeedyAssetServletUtil.ByteRange range = ranges.get(0);
input = new RandomAccessFile(f, "r");
// Check if Range is syntactically valid. If not, then return 416.
if (range.start > range.end) {
response.setHeader("Content-Range", "bytes */" + data.length); // Required in 416.
response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
return;
}
response.setContentType(file.getMimeType());
response.setHeader("Content-Range", "bytes " + range.start + "-" + range.end + "/" + range.total);
response.setHeader("Content-Length", String.valueOf(range.length));
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); // 206.
SpeedyAssetServletUtil.copy(input, out, range.start, range.length);
}else{
response.setContentType("multipart/byteranges; boundary=" + SpeedyAssetServletUtil.MULTIPART_BOUNDARY);
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
input = new RandomAccessFile(f, "r");
for (SpeedyAssetServletUtil.ByteRange r : ranges) {
if (r.start > r.end) {
response.setHeader("Content-Range", "bytes */" + data.length); // Required in 416.
response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
return;
}
// Add multipart boundary and header fields for every range.
out.println();
out.println("--" + SpeedyAssetServletUtil.MULTIPART_BOUNDARY);
out.println("Content-Type: " + file.getMimeType());
out.println("Content-Range: bytes " + r.start + "-" + r.end + "/" + r.total);
out.println();
// Copy single part range of multi part range.
SpeedyAssetServletUtil.copy(input, out, r.start, r.length);