/* * #%L * Alfresco Repository WAR Community * %% * Copyright (C) 2005 - 2016 Alfresco Software Limited * %% * This file is part of the Alfresco software. * If the software was purchased under a paid Alfresco license, the terms of * the paid license agreement will prevail. Otherwise, the software is * provided under the following open source license terms: * * Alfresco is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . * #L% */ package org.alfresco.web.app.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.transaction.TransactionService; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Servlet responsible for streaming node content from the repo directly to the response stream. * The appropriate mimetype is calculated based on filename extension. *

* The URL to the servlet should be generated thus: *

/alfresco/download/attach/workspace/SpacesStore/0000-0000-0000-0000/myfile.pdf
* or *
/alfresco/download/direct/workspace/SpacesStore/0000-0000-0000-0000/myfile.pdf
* or *
/alfresco/download/[direct|attach]?path=/Company%20Home/MyFolder/myfile.pdf
* The protocol, followed by either the store and Id (NodeRef) or instead specify a name based * encoded Path to the content, note that the filename element is used for mimetype lookup and * as the returning filename for the response stream. *

* The 'attach' or 'direct' element is used to indicate whether to display the stream directly * in the browser or download it as a file attachment. *

* By default, the download assumes that the content is on the * {@link org.alfresco.model.ContentModel#PROP_CONTENT content property}.
* To retrieve the content of a specific model property, use a 'property' arg, providing the workspace, * node ID AND the qualified name of the property. *

* Like most Alfresco servlets, the URL may be followed by a valid 'ticket' argument for authentication: * ?ticket=1234567890 *

* And/or also followed by the "?guest=true" argument to force guest access login for the URL. If the * guest=true parameter is used the current session will be logged out and the guest user logged in. * Therefore upon completion of this request the current user will be "guest". *

* If the user attempting the request is not authorised to access the requested node the login page * will be redirected to. * * @author Kevin Roast * @author gavinc */ public class DownloadContentServlet extends BaseDownloadContentServlet { private static final long serialVersionUID = -576405943603122206L; private static Log logger = LogFactory.getLog(DownloadContentServlet.class); private static final String DOWNLOAD_URL = "/d/" + URL_ATTACH + "/{0}/{1}/{2}/{3}"; private static final String BROWSER_URL = "/d/" + URL_DIRECT + "/{0}/{1}/{2}/{3}"; @Override protected Log getLogger() { return logger; } /* (non-Javadoc) * @see javax.servlet.http.HttpServlet#doHead(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @Override protected void doHead(final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException { if (logger.isDebugEnabled()) { String queryString = req.getQueryString(); logger.debug("Authenticating (HEAD) request to URL: " + req.getRequestURI() + ((queryString != null && queryString.length() > 0) ? ("?" + queryString) : "")); } AuthenticationStatus status = servletAuthenticate(req, res); if (status == AuthenticationStatus.Failure) { return; } ServiceRegistry serviceRegistry = getServiceRegistry(getServletContext()); TransactionService transactionService = serviceRegistry.getTransactionService(); RetryingTransactionCallback processCallback = new RetryingTransactionCallback() { public Void execute() throws Throwable { processDownloadRequest(req, res, true, false); return null; } }; transactionService.getRetryingTransactionHelper().doInTransaction(processCallback, true); } /** * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ protected void doGet(final HttpServletRequest req, final HttpServletResponse res) throws ServletException, IOException { if (logger.isDebugEnabled()) { String queryString = req.getQueryString(); logger.debug("Authenticating (GET) request to URL: " + req.getRequestURI() + ((queryString != null && queryString.length() > 0) ? ("?" + queryString) : "")); } AuthenticationStatus status = servletAuthenticate(req, res); if (status == AuthenticationStatus.Failure) { return; } ServiceRegistry serviceRegistry = getServiceRegistry(getServletContext()); TransactionService transactionService = serviceRegistry.getTransactionService(); RetryingTransactionCallback processCallback = new RetryingTransactionCallback() { public Void execute() throws Throwable { processDownloadRequest(req, res, true, true); return null; } }; transactionService.getRetryingTransactionHelper().doInTransaction(processCallback, true); } /** * Helper to generate a URL to a content node for downloading content from the server. * The content is supplied as an HTTP1.1 attachment to the response. This generally means * a browser should prompt the user to save the content to specified location. * * @param ref NodeRef of the content node to generate URL for (cannot be null) * @param name File name to return in the URL (cannot be null) * * @return URL to download the content from the specified node */ public final static String generateDownloadURL(NodeRef ref, String name) { return generateUrl(DOWNLOAD_URL, ref, name); } /** * Helper to generate a URL to a content node for downloading content from the server. * The content is supplied directly in the reponse. This generally means a browser will * attempt to open the content directly if possible, else it will prompt to save the file. * * @param ref NodeRef of the content node to generate URL for (cannot be null) * @param name File name to return in the URL (cannot be null) * * @return URL to download the content from the specified node */ public final static String generateBrowserURL(NodeRef ref, String name) { return generateUrl(BROWSER_URL, ref, name); } }