/* * Created on 23.8.2004 * * Copyright (C) 2004 Idega hf. All Rights Reserved. * * This software is the proprietary information of Idega hf. Use is subject to * license terms. */ package com.idega.io; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.Collection; import java.util.logging.Level; import java.util.logging.Logger; import javax.ejb.FinderException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.idega.core.file.business.ICFileSystem; import com.idega.core.file.business.ICFileSystemFactory; import com.idega.core.file.data.ICFile; import com.idega.core.file.data.ICFileHome; import com.idega.core.file.util.MimeTypeUtil; import com.idega.data.IDOLookup; import com.idega.presentation.IWContext; import com.idega.user.data.User; import com.idega.util.CoreConstants; import com.idega.util.CoreUtil; import com.idega.util.FileUtil; import com.idega.util.IOUtil; import com.idega.util.ListUtil; import com.idega.util.StringUtil; /** * @author aron * * DownloadWriter To be used when files are downloaded to the user. The response * is set so that the client browser opens a save dialog. Handles both files * from database and absolute paths from filesystem if read permission is active */ public class DownloadWriter implements MediaWritable { private static final Logger LOGGER = Logger.getLogger(DownloadWriter.class.getName()); public final static String PRM_ABSOLUTE_FILE_PATH = "abs_fpath"; public final static String PRM_RELATIVE_FILE_PATH = "rel_fpath"; public final static String PRM_FILE_NAME = "alt_f_name"; public final static String PRM_FILE_ID = "fileId"; private File file = null; private ICFile icFile = null; private URL url = null; private String fileName; protected void setFile(File file) { if (file == null) { LOGGER.warning("File is undefined!"); return; } if (!file.exists()) { LOGGER.warning("File " + file + " does not exist!"); return; } if (!file.canRead()) { LOGGER.warning("There are no rights provided to read from file: " + file); return; } this.file = file; } /* * (non-Javadoc) * * @see com.idega.io.MediaWritable#getMimeType() */ @Override public String getMimeType() { if (fileName == null) return MimeTypeUtil.MIME_TYPE_APPLICATION; String mimeType = MimeTypeUtil.resolveMimeTypeFromFileName(fileName); return StringUtil.isEmpty(mimeType) ? MimeTypeUtil.MIME_TYPE_APPLICATION : mimeType; } /* * (non-Javadoc) * * @see com.idega.io.MediaWritable#init(javax.servlet.http.HttpServletRequest, * com.idega.presentation.IWContext) */ @Override public void init(HttpServletRequest req, IWContext iwc) { String fileId = iwc.getParameter(PRM_FILE_ID); String absPath = iwc.getParameter(PRM_ABSOLUTE_FILE_PATH); String relPath = iwc.getParameter(PRM_RELATIVE_FILE_PATH); String altFileName = iwc.getParameter(PRM_FILE_NAME); if (fileId != null) { try { ICFileSystem fsystem = ICFileSystemFactory.getFileSystem(iwc); String fileURL = fsystem.getFileURI(Integer.valueOf(fileId).intValue()); this.file = new File(iwc.getIWMainApplication().getRealPath(fileURL)); this.icFile = ((ICFileHome) IDOLookup.getHome(ICFile.class)).findByPrimaryKey(Integer.valueOf(fileId)); setAsDownload(iwc, this.file.getName(), (int) this.file.length()); } catch (Exception e) { this.icFile = null; } } else if (absPath != null) { this.file = new File(absPath); if (this.file != null && this.file.exists() && this.file.canRead()) { setAsDownload(iwc, this.file.getName(), (int) this.file.length()); } } else if (relPath != null && altFileName == null) { this.file = new File(iwc.getIWMainApplication().getRealPath(relPath)); if (this.file != null && this.file.exists() && this.file.canRead()) { setAsDownload(iwc, this.file.getName(), (int) this.file.length()); } } else if (relPath != null && altFileName != null) { try { if(relPath.startsWith("/")){ relPath = relPath.substring(1); } this.url = new URL(iwc.getServerURL()+relPath); setAsDownload(iwc, altFileName, -1); } catch (MalformedURLException e) { LOGGER.log(Level.WARNING, "Error creating URL: " + relPath, e); } } } protected File getFileFromRepository(String pathInRepository) throws IOException { return CoreUtil.getFileFromRepository(pathInRepository); } /* * (non-Javadoc) * * @see com.idega.io.MediaWritable#writeTo(java.io.OutputStream) */ @Override public void writeTo(OutputStream out) throws IOException { InputStream downloadStream = null; if (this.file != null && this.file.exists() && this.file.canRead() && this.file.length() > 0) { LOGGER.info("Dowloading file: " + file); downloadStream = new BufferedInputStream(new FileInputStream(this.file)); } else if (this.icFile != null) { downloadStream = new BufferedInputStream(this.icFile.getFileValue()); } else if (this.url != null) { //added for real relative path streaming downloadStream = new BufferedInputStream(this.url.openStream()); } if (downloadStream == null) { throw new IOException("No file to download!"); } try { FileUtil.streamToOutputStream(downloadStream, out); } catch(Exception e) { LOGGER.log(Level.WARNING, "Error streaming from input to output streams", e); } finally { out.flush(); IOUtil.closeOutputStream(out); IOUtil.closeInputStream(downloadStream); } } public void setAsDownload(IWContext iwc, String filename, int fileLength) { setAsDownload(iwc, filename, fileLength, CoreConstants.EMPTY); } public void setAsDownload(IWContext iwc, String filename, int fileLength, Object icFileIdOrHashValue) { if (icFileIdOrHashValue instanceof String) { setAsDownload(iwc, filename, fileLength, icFileIdOrHashValue.toString()); } else if (icFileIdOrHashValue instanceof Integer) { setAsDownload(iwc, filename, fileLength, (Integer) icFileIdOrHashValue); } else { setAsDownload(iwc, filename, fileLength); } } public void setAsDownload(IWContext iwc, String filename, int fileLength, String icFileId) { this.fileName = filename; if (!StringUtil.isEmpty(icFileId)) { markFileAsDownloaded(iwc, icFileId); } sendResponse(iwc, filename, fileLength); } public void setAsDownload(IWContext iwc, String filename, int fileLength, Integer hash) { this.fileName = filename; if (hash != null) { markFileAsDownloaded(iwc, hash); } sendResponse(iwc, filename, fileLength); } private void sendResponse(IWContext iwc, String filename, int fileLength) { HttpServletResponse response = iwc.getResponse(); response.setHeader("Expires", String.valueOf(0)); response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0"); response.setHeader("Content-Type", "application/force-download"); response.setHeader("Content-Type", "application/octet-stream"); response.setHeader("Content-Type", "application/download"); response.setHeader("Content-Disposition", "attachment;filename=\"" + filename + "\""); response.setHeader("Content-Transfer-Encoding", "binary"); if (fileLength > 0) response.setContentLength(fileLength); } protected boolean markFileAsDownloaded(IWContext iwc, Integer hash) { return markFileAsDownloaded(iwc, getFile(hash)); } protected boolean markFileAsDownloaded(IWContext iwc, String icFileId) { return markFileAsDownloaded(iwc, getFile(icFileId)); } protected boolean markFileAsDownloaded(IWContext iwc, ICFile attachment) { if (attachment == null) { return false; } User user = iwc.isLoggedOn() ? iwc.getCurrentUser() : null; if (user == null) { return false; } Collection<User> downloadedBy = attachment.getDownloadedBy(); if (!ListUtil.isEmpty(downloadedBy) && downloadedBy.contains(user)) { return true; } try { attachment.addDownloadedBy(user); attachment.store(); return true; } catch(Exception e) { LOGGER.log(Level.WARNING, "Error while setting that user " + user + " has downloaded file " + attachment, e); } return false; } private ICFile getFile(Integer hash) { if (hash == null) { return null; } ICFileHome fileHome = null; try { fileHome = (ICFileHome) IDOLookup.getHome(ICFile.class); } catch(Exception e) { LOGGER.log(Level.WARNING, "Error getting instance of " + ICFileHome.class, e); } if (fileHome == null) { return null; } ICFile file = null; try { file = fileHome.findByHash(hash); } catch(FinderException e) { } catch(Exception e) { LOGGER.log(Level.WARNING, "Error getting file by hash: " + hash, e); } if (file == null) { file = createFile(fileHome, hash); } return file; } private ICFile createFile(ICFileHome fileHome, Integer hash) { try { ICFile file = fileHome.create(); file.setHash(hash); if (!StringUtil.isEmpty(getFileName())) { file.setName(URLEncoder.encode(getFileName(), CoreConstants.ENCODING_UTF8)); } file.store(); return file; } catch(Exception e) { LOGGER.log(Level.WARNING, "Error while creating file using hash: " + hash, e); } return null; } private ICFile getFile(String icFileId) { if (StringUtil.isEmpty(icFileId)) { return null; } try { ICFileHome fileHome = (ICFileHome) IDOLookup.getHome(ICFile.class); return fileHome.findByPrimaryKey(icFileId); } catch(Exception e) {} return null; } public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } protected File getFile() { return file; } protected ICFile getICFile() { return icFile; } protected void setICFile(ICFile icFile) { this.icFile = icFile; } }