AbstractUploadHandler.java
/*
* Copyright (c) 2002-2022, City of Paris
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice
* and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* License 1.0
*/
package fr.paris.lutece.plugins.dansmarue.modules.rest.service.upload.handler;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Value;
import fr.paris.lutece.plugins.asynchronousupload.service.AbstractAsynchronousUploadHandler;
import fr.paris.lutece.portal.service.i18n.I18nService;
import fr.paris.lutece.portal.service.util.AppException;
import fr.paris.lutece.util.filesystem.UploadUtil;
/**
* AbstractUploadHandler.
*/
public abstract class AbstractUploadHandler extends AbstractAsynchronousUploadHandler
{
/** The upload directory. */
@Value( "${signalement.directory.upload}" )
protected String _uploadDirectory;
/** The max file size. */
@Value( "${signalement.upload.max.file.size}" )
private String _maxFileSize;
/** The max category files count. */
@Value( "${signalement.upload.max.category.files.count}" )
private Integer _maxCategoryFilesCount;
/**
* Gets the max file size.
*
* @return the max file size
*/
public String getMaxFileSize( )
{
return _maxFileSize;
}
/** The Constant PREFIX_ENTRY_ID. */
private static final String PREFIX_ENTRY_ID = "dansmarue_";
/** The Constant LOGGER. */
private static final Log LOGGER = LogFactory.getLog( AbstractUploadHandler.class );
/** The Constant ERROR_EXTENSION. */
public static final String ERROR_EXTENSION = "module.dansmarue.rest.message.upload.file.error.extension";
/** The Constant ERROR_FILES_COUNT. */
public static final String ERROR_FILES_COUNT = "module.dansmarue.rest.message.upload.file.error.files.count";
/** The Constant HANDLER_NAME. */
private static final String HANDLER_NAME = "DansmarueAsynchronousUploadHandler";
/** The extension list. */
private static String[] _extensionList = { "jpeg", "png", "jpg" };
/**
* Constructor.
*/
public AbstractUploadHandler( )
{
}
/**
* {@inheritDoc}
*/
@Override
public void addFileItemToUploadedFilesList( FileItem fileItem, String strFieldName, HttpServletRequest request )
{
String strFileName = UploadUtil.cleanFileName( fileItem.getName( ).trim( ) );
initMap( request.getSession( ), PREFIX_ENTRY_ID + strFieldName );
List<FileItem> uploadedFiles = getListUploadedFiles( strFieldName, request.getSession( ) );
if ( uploadedFiles != null )
{
boolean bNew = true;
if ( !uploadedFiles.isEmpty( ) )
{
Iterator<FileItem> iterUploadedFiles = uploadedFiles.iterator( );
while ( bNew && iterUploadedFiles.hasNext( ) )
{
FileItem uploadedFile = iterUploadedFiles.next( );
String strUploadedFileName = UploadUtil.cleanFileName( uploadedFile.getName( ).trim( ) );
bNew = !( StringUtils.equals( strUploadedFileName, strFileName ) && ( uploadedFile.getSize( ) == fileItem.getSize( ) ) );
}
}
if ( bNew )
{
uploadedFiles.add( fileItem );
}
}
}
/**
* {@inheritDoc}
*/
@Override
public String canUploadFiles( HttpServletRequest request, String strFieldName, List<FileItem> listFileItemsToUpload, Locale locale )
{
if ( StringUtils.isNotBlank( strFieldName ) )
{
if ( getListUploadedFiles( strFieldName, request.getSession( ) ).size( ) >= _maxCategoryFilesCount )
{
return I18nService.getLocalizedString( ERROR_FILES_COUNT, new Object [ ] {
_maxCategoryFilesCount
}, locale );
}
for ( FileItem fileItem : listFileItemsToUpload )
{
if ( !ArrayUtils.contains( _extensionList, FilenameUtils.getExtension( fileItem.getName( ).toLowerCase( ) ) ) )
{
return I18nService.getLocalizedString( ERROR_EXTENSION, locale ) + StringUtils.join( _extensionList, ", " );
}
}
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public String getHandlerName( )
{
return HANDLER_NAME;
}
/**
* return picture file.
*
* @param request
* the http request.
* @param strFieldName
* the field name.
* @return the file item
*/
public FileItem getFile( HttpServletRequest request, String strFieldName )
{
if ( StringUtils.isNotBlank( strFieldName ) )
{
List<FileItem> listUploadedFileItems = getListUploadedFiles( strFieldName, request.getSession( ) );
if ( !listUploadedFileItems.isEmpty( ) )
{
return listUploadedFileItems.get( 0 );
}
}
return null;
}
/**
* {@inheritDoc}
*/
@Override
public List<FileItem> getListUploadedFiles( String strFieldName, HttpSession session )
{
if ( StringUtils.isBlank( strFieldName ) )
{
throw new AppException( "id field name is not provided for the current file upload" );
}
initMap( session, strFieldName );
Map<String, List<FileItem>> mapFileItemsSession = getMapAsynchronousUpload( ).get( session.getId( ) );
return mapFileItemsSession.get( strFieldName );
}
/**
* {@inheritDoc}
*/
@Override
public void removeFileItem( String strFieldName, HttpSession session, int nIndex )
{
List<FileItem> uploadedFiles = getListUploadedFiles( strFieldName, session );
remove( strFieldName, session, nIndex, uploadedFiles );
}
/**
* Inits the map.
*
* @param session
* the session
* @param strFieldName
* the str field name
*/
private void initMap( HttpSession session, String strFieldName )
{
String strSessionId = session.getId( );
Map<String, List<FileItem>> mapFileItemsSession = getMapAsynchronousUpload( ).get( strSessionId );
if ( mapFileItemsSession == null )
{
synchronized( this )
{
mapFileItemsSession = getMapAsynchronousUpload( ).get( strSessionId );
if ( mapFileItemsSession == null )
{
mapFileItemsSession = new ConcurrentHashMap<>( );
getMapAsynchronousUpload( ).put( strSessionId, mapFileItemsSession );
}
}
}
mapFileItemsSession.computeIfAbsent( strFieldName, k -> new ArrayList<>( ) );
}
/**
* Removes the file.
*
* @param session
* the session
* @param fileToSave
* the file to save
* @param categoryName
* the category name
*/
private void removeFile( HttpSession session, FileItem fileToSave, String categoryName )
{
String id = getIdInSession( session );
if ( ( null == id ) || ( null == fileToSave ) || StringUtils.isEmpty( categoryName ) )
{
return;
}
String categoryPath = FilenameUtils.concat( getUploadDirectory( ), id );
categoryPath = FilenameUtils.concat( categoryPath, categoryName );
String fileName = FilenameUtils.getName( fileToSave.getName( ) );
try
{
String filePath = FilenameUtils.concat( categoryPath, fileName );
Path path = Paths.get( filePath );
Files.deleteIfExists( path );
LOGGER.info( "Fichier supprimé avec succès : " + fileName );
}
catch( IOException ex )
{
LOGGER.error( "Impossible de supprimer le fichier : " + fileName, ex );
}
}
/**
* Removes the.
*
* @param strFieldName
* the str field name
* @param session
* the session
* @param nIndex
* the n index
* @param uploadedFiles
* the uploaded files
*/
private void remove( String strFieldName, HttpSession session, int nIndex, List<FileItem> uploadedFiles )
{
if ( ( uploadedFiles != null ) && !uploadedFiles.isEmpty( ) && ( uploadedFiles.size( ) > nIndex ) )
{
FileItem fileItem = uploadedFiles.remove( nIndex );
removeFile( session, fileItem, strFieldName );
fileItem.delete( );
}
}
/**
* Checks for file.
*
* @param request
* the request
* @param strFieldName
* the str field name
* @return true, if successful
*/
public boolean hasFile( HttpServletRequest request, String strFieldName )
{
if ( StringUtils.isNotBlank( strFieldName ) )
{
List<FileItem> listUploadedFileItems = getListUploadedFiles( strFieldName, request.getSession( ) );
if ( !listUploadedFileItems.isEmpty( ) )
{
return true;
}
}
return false;
}
/**
* Gets the id in session.
*
* @param session
* the session
* @return the id in session
*/
public abstract String getIdInSession( HttpSession session );
/**
* Gets the upload directory.
*
* @return the upload directory
*/
public abstract String getUploadDirectory( );
/**
* Gets the map asynchronous upload.
*
* @return the map asynchronous upload
*/
abstract Map<String, Map<String, List<FileItem>>> getMapAsynchronousUpload( );
}