View Javadoc
1   /*
2    * Copyright (c) 2002-2021, City of Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.blobstore.web;
35  
36  import fr.paris.lutece.plugins.blobstore.service.BlobStoreFileItem;
37  import fr.paris.lutece.plugins.blobstore.service.IBlobStoreService;
38  import fr.paris.lutece.plugins.blobstore.service.NoSuchBlobException;
39  import fr.paris.lutece.plugins.blobstore.util.BlobStoreLibConstants;
40  import fr.paris.lutece.plugins.blobstore.util.BlobStoreUtils;
41  import fr.paris.lutece.portal.service.fileupload.FileUploadService;
42  import fr.paris.lutece.portal.service.i18n.I18nService;
43  import fr.paris.lutece.portal.service.spring.SpringContextService;
44  import fr.paris.lutece.portal.service.util.AppLogService;
45  import fr.paris.lutece.util.filesystem.UploadUtil;
46  
47  import org.apache.commons.io.IOUtils;
48  import org.apache.commons.lang3.StringUtils;
49  
50  import org.springframework.beans.factory.NoSuchBeanDefinitionException;
51  
52  import java.io.IOException;
53  import java.io.InputStream;
54  import java.io.OutputStream;
55  
56  import javax.servlet.http.HttpServletRequest;
57  import javax.servlet.http.HttpServletResponse;
58  
59  /**
60   * Provides blob download.
61   *
62   */
63  public class BlobStoreJspBean
64  {
65      private static final String PROPERTY_MESSAGE_NO_SUCH_BLOB = "blobstore.download.noSuchBlob";
66      private static final String PROPERTY_MESSAGE_ERROR_RETRIEVING_BLOB = "blobstore.download.error";
67      private static final String PROPERTY_MESSAGE_NO_SUCH_BLOBSTORE = "blobstore.download.noSuchBlobStore";
68      private static final String PROPERTY_MESSAGE_ACCESS_DENIED = "blobstore.download.accessDenied";
69  
70      /**
71       * Download a file : blob key is the metadata key
72       * 
73       * @param request
74       *            the request
75       * @param response
76       *            the response
77       * @return the error message if any, <code>null</code> otherwise.
78       */
79      public String doDownloadFile( HttpServletRequest request, HttpServletResponse response )
80      {
81          String strErrorMessage = null;
82  
83          if ( BlobStoreUtils.getRequestAuthenticator( ).isRequestAuthenticated( request ) )
84          {
85              String strBlobKey = request.getParameter( BlobStoreLibConstants.PARAMETER_BLOB_KEY );
86              String strBlobstore = request.getParameter( BlobStoreLibConstants.PARAMETER_BLOB_STORE );
87  
88              IBlobStoreService blobstoreService = (IBlobStoreService) SpringContextService.getBean( strBlobstore );
89  
90              if ( blobstoreService != null )
91              {
92                  if ( StringUtils.isNotBlank( strBlobKey ) )
93                  {
94                      try
95                      {
96                          BlobStoreFileItem fileItem = new BlobStoreFileItem( strBlobKey, blobstoreService );
97                          DownloadableFile file = new DownloadableFile( );
98                          file.setContentType( fileItem.getContentType( ) );
99                          file.setFileName( UploadUtil.cleanFileName( FileUploadService.getFileNameOnly( fileItem ) ) );
100                         file.setInputStream( fileItem.getInputStream( ) );
101                         file.setSize( (int) fileItem.getSize( ) );
102 
103                         strErrorMessage = writeFile( request, response, file );
104                     }
105                     catch( IOException ioe )
106                     {
107                         AppLogService.error( ioe.getMessage( ), ioe );
108                         // error message
109                         strErrorMessage = I18nService.getLocalizedString( PROPERTY_MESSAGE_ERROR_RETRIEVING_BLOB, request.getLocale( ) );
110                     }
111                     catch( NoSuchBlobException nsbe )
112                     {
113                         // error message not found
114                         strErrorMessage = I18nService.getLocalizedString( PROPERTY_MESSAGE_NO_SUCH_BLOB, request.getLocale( ) );
115                     }
116                 }
117                 else
118                 {
119                     // error message key
120                     strErrorMessage = I18nService.getLocalizedString( PROPERTY_MESSAGE_NO_SUCH_BLOB, request.getLocale( ) );
121                 }
122             }
123             else
124             {
125                 // error message blob store
126                 strErrorMessage = I18nService.getLocalizedString( PROPERTY_MESSAGE_NO_SUCH_BLOBSTORE, request.getLocale( ) );
127             }
128         }
129         else
130         {
131             strErrorMessage = I18nService.getLocalizedString( PROPERTY_MESSAGE_ACCESS_DENIED, request.getLocale( ) );
132         }
133 
134         // nothing to return
135         return strErrorMessage;
136     }
137 
138     /**
139      * Downloads a blob.
140      * 
141      * @param request
142      *            the requrest
143      * @param response
144      *            the response
145      * @return the error message if any, <code>null</code> otherwise.
146      */
147     public String doDownloadBlob( HttpServletRequest request, HttpServletResponse response )
148     {
149         String strBlobKey = request.getParameter( BlobStoreLibConstants.PARAMETER_BLOB_KEY );
150         String strBlobstore = request.getParameter( BlobStoreLibConstants.PARAMETER_BLOB_STORE );
151 
152         IBlobStoreService blobstoreService;
153 
154         try
155         {
156             blobstoreService = (IBlobStoreService) SpringContextService.getBean( strBlobstore );
157         }
158         catch( NoSuchBeanDefinitionException ex )
159         {
160             blobstoreService = null;
161         }
162 
163         String strErrorMessage = null;
164 
165         if ( blobstoreService != null )
166         {
167             if ( StringUtils.isNotBlank( strBlobKey ) )
168             {
169                 // content type is unknown
170                 // file name is blob key
171                 // size is unknown
172                 InputStream is = blobstoreService.getBlobInputStream( strBlobKey );
173 
174                 if ( is != null )
175                 {
176                     DownloadableFile file = new DownloadableFile( );
177                     file.setFileName( strBlobKey );
178                     file.setInputStream( is );
179 
180                     strErrorMessage = writeFile( request, response, file );
181                 }
182                 else
183                 {
184                     // error message
185                     strErrorMessage = I18nService.getLocalizedString( PROPERTY_MESSAGE_ERROR_RETRIEVING_BLOB, request.getLocale( ) );
186                 }
187             }
188             else
189             {
190                 // error message key
191                 strErrorMessage = I18nService.getLocalizedString( PROPERTY_MESSAGE_NO_SUCH_BLOB, request.getLocale( ) );
192             }
193         }
194         else
195         {
196             // error message blob store
197             strErrorMessage = I18nService.getLocalizedString( PROPERTY_MESSAGE_NO_SUCH_BLOBSTORE, request.getLocale( ) );
198         }
199 
200         // nothing to return
201         return strErrorMessage;
202     }
203 
204     /**
205      * Writes the file to the response
206      * 
207      * @param request
208      *            the request
209      * @param response
210      *            the response
211      * @param file
212      *            the file
213      * @return the error message if any, <code>null</code> othrewise.
214      */
215     private String writeFile( HttpServletRequest request, HttpServletResponse response, DownloadableFile file )
216     {
217         String strErrorMessage = null;
218         OutputStream os = null;
219         InputStream is = file.getInputStream( );
220 
221         try
222         {
223             response.setHeader( "Content-Disposition", "attachment ;filename=\"" + file.getFileName( ) );
224             response.setHeader( "Pragma", "public" );
225             response.setHeader( "Expires", "0" );
226             response.setHeader( "Cache-Control", "must-revalidate,post-check=0,pre-check=0" );
227 
228             if ( file.getContentType( ) != null )
229             {
230                 response.setContentType( file.getContentType( ) );
231             }
232             else
233             {
234                 response.setContentType( "application/force-download" );
235             }
236 
237             if ( file.getSize( ) != 0 )
238             {
239                 response.setContentLength( file.getSize( ) );
240             }
241 
242             os = response.getOutputStream( );
243             IOUtils.copy( is, os );
244         }
245         catch( IOException ioe )
246         {
247             AppLogService.error( ioe.getMessage( ), ioe );
248             // error message
249             strErrorMessage = I18nService.getLocalizedString( PROPERTY_MESSAGE_ERROR_RETRIEVING_BLOB, request.getLocale( ) );
250         }
251         finally
252         {
253             IOUtils.closeQuietly( is );
254             IOUtils.closeQuietly( os );
255         }
256 
257         return strErrorMessage;
258     }
259 
260     /**
261      *
262      * DownloadableFile
263      *
264      */
265     private static class DownloadableFile
266     {
267         private String _strFileName;
268         private String _strContentType;
269         private int _nSize;
270         private InputStream _inputStream;
271 
272         /**
273          * Gets the input stream
274          * 
275          * @return the input stream
276          */
277         public InputStream getInputStream( )
278         {
279             return _inputStream;
280         }
281 
282         /**
283          * Sets the input stream
284          * 
285          * @param inputStream
286          *            the input stream
287          */
288         public void setInputStream( InputStream inputStream )
289         {
290             _inputStream = inputStream;
291         }
292 
293         /**
294          * Gets the file name
295          * 
296          * @return the file name
297          */
298         public String getFileName( )
299         {
300             return _strFileName;
301         }
302 
303         /**
304          * Sets the file name
305          * 
306          * @param strFileName
307          *            the file name
308          */
309         public void setFileName( String strFileName )
310         {
311             _strFileName = strFileName;
312         }
313 
314         /**
315          * Gets the file size
316          * 
317          * @return the file size
318          */
319         public int getSize( )
320         {
321             return _nSize;
322         }
323 
324         /**
325          * Sets the file size
326          * 
327          * @param nSize
328          *            the file size
329          */
330         public void setSize( int nSize )
331         {
332             _nSize = nSize;
333         }
334 
335         /**
336          * Gets the content type
337          * 
338          * @return the content type
339          */
340         public String getContentType( )
341         {
342             return _strContentType;
343         }
344 
345         /**
346          * Sets the content type
347          * 
348          * @param strContentType
349          *            the content type
350          */
351         public void setContentType( String strContentType )
352         {
353             _strContentType = strContentType;
354         }
355     }
356 }