391080 Multipart temp files can be left on disk from Request.getPart and getParts
This commit is contained in:
parent
25cdef966c
commit
36a2ed10be
|
@ -50,6 +50,8 @@ import javax.servlet.ServletInputStream;
|
|||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletRequestAttributeEvent;
|
||||
import javax.servlet.ServletRequestAttributeListener;
|
||||
import javax.servlet.ServletRequestEvent;
|
||||
import javax.servlet.ServletRequestListener;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -80,6 +82,7 @@ import org.eclipse.jetty.server.handler.ContextHandler.Context;
|
|||
import org.eclipse.jetty.util.Attributes;
|
||||
import org.eclipse.jetty.util.AttributesMap;
|
||||
import org.eclipse.jetty.util.LazyList;
|
||||
import org.eclipse.jetty.util.MultiException;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.eclipse.jetty.util.MultiPartInputStream;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
|
@ -123,12 +126,44 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
public class Request implements HttpServletRequest
|
||||
{
|
||||
public static final String __MULTIPART_CONFIG_ELEMENT = "org.eclipse.multipartConfig";
|
||||
public static final String __MULTIPART_INPUT_STREAM = "org.eclipse.multiPartInputStream";
|
||||
|
||||
private static final Logger LOG = Log.getLogger(Request.class);
|
||||
|
||||
private static final String __ASYNC_FWD = "org.eclipse.asyncfwd";
|
||||
private static final Collection __defaultLocale = Collections.singleton(Locale.getDefault());
|
||||
private static final int __NONE = 0, _STREAM = 1, __READER = 2;
|
||||
|
||||
public static class MultiPartCleanerListener implements ServletRequestListener
|
||||
{
|
||||
|
||||
@Override
|
||||
public void requestDestroyed(ServletRequestEvent sre)
|
||||
{
|
||||
//Clean up any tmp files created by MultiPartInputStream
|
||||
MultiPartInputStream mpis = (MultiPartInputStream)sre.getServletRequest().getAttribute(__MULTIPART_INPUT_STREAM);
|
||||
if (mpis != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
mpis.deleteParts();
|
||||
}
|
||||
catch (MultiException e)
|
||||
{
|
||||
sre.getServletContext().log("Errors deleting multipart tmp files", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestInitialized(ServletRequestEvent sre)
|
||||
{
|
||||
//nothing to do, multipart config set up by ServletHolder.handle()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static Request getRequest(HttpServletRequest request)
|
||||
{
|
||||
|
@ -1975,6 +2010,7 @@ public class Request implements HttpServletRequest
|
|||
_multiPartInputStream = new MultiPartInputStream(getInputStream(),
|
||||
getContentType(),(MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT),
|
||||
(_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
|
||||
setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream);
|
||||
Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
|
||||
for (Part p:parts)
|
||||
{
|
||||
|
@ -2006,6 +2042,7 @@ public class Request implements HttpServletRequest
|
|||
_multiPartInputStream = new MultiPartInputStream(getInputStream(),
|
||||
getContentType(),(MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT),
|
||||
(_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
|
||||
setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream);
|
||||
Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
|
||||
for (Part p:parts)
|
||||
{
|
||||
|
|
|
@ -514,6 +514,8 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
|||
initJspServlet();
|
||||
}
|
||||
|
||||
initMultiPart();
|
||||
|
||||
_servlet.init(_config);
|
||||
}
|
||||
catch (UnavailableException e)
|
||||
|
@ -570,6 +572,25 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Register a ServletRequestListener that will ensure tmp multipart
|
||||
* files are deleted when the request goes out of scope.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void initMultiPart () throws Exception
|
||||
{
|
||||
//if this servlet can handle multipart requests, ensure tmp files will be
|
||||
//cleaned up correctly
|
||||
if (((Registration)getRegistration()).getMultipartConfig() != null)
|
||||
{
|
||||
//Register a listener to delete tmp files that are created as a result of this
|
||||
//servlet calling Request.getPart() or Request.getParts()
|
||||
ContextHandler ch = ((ContextHandler.Context)getServletHandler().getServletContext()).getContextHandler();
|
||||
ch.addEventListener(new Request.MultiPartCleanerListener());
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
|
|
@ -84,7 +84,7 @@ import org.eclipse.jetty.util.TypeUtil;
|
|||
public class MultiPartFilter implements Filter
|
||||
{
|
||||
public final static String CONTENT_TYPE_SUFFIX=".org.eclipse.jetty.servlet.contentType";
|
||||
private final static String MULTIPART = "org.eclipse.jetty.servlet.MultiPartInputStream";
|
||||
private final static String MULTIPART = "org.eclipse.jetty.servlet.MultiPartFile.multiPartInputStream";
|
||||
private File tempdir;
|
||||
private boolean _deleteFiles;
|
||||
private ServletContext _context;
|
||||
|
@ -191,23 +191,24 @@ public class MultiPartFilter implements Filter
|
|||
deleteFiles(request);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private void deleteFiles(ServletRequest request)
|
||||
{
|
||||
if (!_deleteFiles)
|
||||
return;
|
||||
|
||||
MultiPartInputStream mpis = (MultiPartInputStream)request.getAttribute(MULTIPART);
|
||||
if (mpis != null)
|
||||
{
|
||||
Collection<Part> parts = mpis.getParsedParts();
|
||||
for (Part p:parts)
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
p.delete();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
_context.log("Failed to delete "+p.getName(),e);
|
||||
}
|
||||
mpis.deleteParts();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_context.log("Error deleting multipart tmp files", e);
|
||||
}
|
||||
}
|
||||
request.removeAttribute(MULTIPART);
|
||||
|
|
|
@ -236,7 +236,7 @@ public class MultiPartInputStream
|
|||
*/
|
||||
public long getSize()
|
||||
{
|
||||
return _size;
|
||||
return _size;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -322,6 +322,7 @@ public class MultiPartInputStream
|
|||
_contextTmpDir = contextTmpDir;
|
||||
if (_contextTmpDir == null)
|
||||
_contextTmpDir = new File (System.getProperty("java.io.tmpdir"));
|
||||
|
||||
if (_config == null)
|
||||
_config = new MultipartConfigElement(_contextTmpDir.getAbsolutePath());
|
||||
}
|
||||
|
@ -340,6 +341,25 @@ public class MultiPartInputStream
|
|||
}
|
||||
return parts;
|
||||
}
|
||||
|
||||
public void deleteParts ()
|
||||
throws MultiException
|
||||
{
|
||||
Collection<Part> parts = getParsedParts();
|
||||
MultiException err = new MultiException();
|
||||
for (Part p:parts)
|
||||
{
|
||||
try
|
||||
{
|
||||
p.delete();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
err.add(e);
|
||||
}
|
||||
}
|
||||
err.ifExceptionThrowMulti();
|
||||
}
|
||||
|
||||
|
||||
public Collection<Part> getParts()
|
||||
|
|
Loading…
Reference in New Issue