org.eclipse.jetty.util.MultiPartInputStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jetty-util Show documentation
Show all versions of jetty-util Show documentation
Utility classes for Jetty
// ========================================================================
// Copyright (c) 2006-2010 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.util;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletException;
import javax.servlet.http.Part;
/**
* MultiPartInputStream
*
* Handle a MultiPart Mime input stream, breaking it up on the boundary into files and strings.
*/
public class MultiPartInputStream
{
public static final MultipartConfigElement __DEFAULT_MULTIPART_CONFIG = new MultipartConfigElement(System.getProperty("java.io.tmpdir"));
protected InputStream _in;
protected MultipartConfigElement _config;
protected String _contentType;
protected MultiMap _parts;
protected File _tmpDir;
protected File _contextTmpDir;
public class MultiPart implements Part
{
protected String _name;
protected String _filename;
protected File _file;
protected OutputStream _out;
protected String _contentType;
protected MultiMap _headers;
protected long _size = 0;
public MultiPart (String name, String filename)
throws IOException
{
_name = name;
_filename = filename;
}
protected void setContentType (String contentType)
{
_contentType = contentType;
}
protected void open()
throws FileNotFoundException, IOException
{
//We will either be writing to a file, if it has a filename on the content-disposition
//and otherwise a byte-array-input-stream, OR if we exceed the getFileSizeThreshold, we
//will need to change to write to a file.
if (_filename != null && _filename.trim().length() > 0)
{
createFile();
}
else
{
//Write to a buffer in memory until we discover we've exceed the
//MultipartConfig fileSizeThreshold
_out = new ByteArrayOutputStream();
}
}
protected void close()
throws IOException
{
_out.close();
}
protected void write (int b)
throws IOException, ServletException
{
if (MultiPartInputStream.this._config.getMaxFileSize() > 0 && _size + 1 > MultiPartInputStream.this._config.getMaxFileSize())
throw new ServletException ("Multipart Mime part "+_name+" exceeds max filesize");
if (MultiPartInputStream.this._config.getFileSizeThreshold() > 0 && _size + 1 > MultiPartInputStream.this._config.getFileSizeThreshold() && _file==null)
createFile();
_out.write(b);
_size ++;
}
protected void write (byte[] bytes, int offset, int length)
throws IOException, ServletException
{
if (MultiPartInputStream.this._config.getMaxFileSize() > 0 && _size + length > MultiPartInputStream.this._config.getMaxFileSize())
throw new ServletException ("Multipart Mime part "+_name+" exceeds max filesize");
if (MultiPartInputStream.this._config.getFileSizeThreshold() > 0 && _size + length > MultiPartInputStream.this._config.getFileSizeThreshold() && _file==null)
createFile();
_out.write(bytes, offset, length);
_size += length;
}
protected void createFile ()
throws IOException
{
_file = File.createTempFile("MultiPart", "", MultiPartInputStream.this._tmpDir);
FileOutputStream fos = new FileOutputStream(_file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
if (_size > 0 && _out != null)
{
//already written some bytes, so need to copy them into the file
_out.flush();
((ByteArrayOutputStream)_out).writeTo(bos);
_out.close();
}
_out = bos;
}
protected void setHeaders(MultiMap headers)
{
_headers = headers;
}
/**
* @see javax.servlet.http.Part#getContentType()
*/
public String getContentType()
{
return _contentType;
}
/**
* @see javax.servlet.http.Part#getHeader(java.lang.String)
*/
public String getHeader(String name)
{
return (String)_headers.getValue(name, 0);
}
/**
* @see javax.servlet.http.Part#getHeaderNames()
*/
public Collection getHeaderNames()
{
return _headers.keySet();
}
/**
* @see javax.servlet.http.Part#getHeaders(java.lang.String)
*/
public Collection getHeaders(String name)
{
return _headers.getValues(name);
}
/**
* @see javax.servlet.http.Part#getInputStream()
*/
public InputStream getInputStream() throws IOException
{
if (_file != null)
{
return new BufferedInputStream (new FileInputStream(_file));
}
else
{
//part content is in a ByteArrayOutputStream
return new ByteArrayInputStream(((ByteArrayOutputStream)_out).toByteArray());
}
}
/**
* @see javax.servlet.http.Part#getName()
*/
public String getName()
{
return _name;
}
/**
* @see javax.servlet.http.Part#getSize()
*/
public long getSize()
{
return _size;
}
/**
* @see javax.servlet.http.Part#write(java.lang.String)
*/
public void write(String fileName) throws IOException
{
if (_file == null)
{
//part data is only in the ByteArrayOutputStream and never been written to disk
_file = new File (_tmpDir, fileName);
BufferedOutputStream bos = null;
try
{
bos = new BufferedOutputStream(new FileOutputStream(_file));
((ByteArrayOutputStream)_out).writeTo(bos);
bos.flush();
}
finally
{
if (bos != null)
bos.close();
}
}
else
{
//the part data is already written to a temporary file, just rename it
_file.renameTo(new File(_tmpDir, fileName));
}
}
/**
* @see javax.servlet.http.Part#delete()
*/
public void delete() throws IOException
{
if (_file != null)
_file.delete();
}
/**
* Get the file, if any, the data has been written to.
* @return
*/
public File getFile ()
{
return _file;
}
/**
* Get the filename from the content-disposition.
* @return null or the filename
*/
public String getContentDispositionFilename ()
{
return _filename;
}
}
/**
* @param in Request input stream
* @param contentType Content-Type header
* @param config MultipartConfigElement
* @param contextTmpDir javax.servlet.context.tempdir
*/
public MultiPartInputStream (InputStream in, String contentType, MultipartConfigElement config, File contextTmpDir)
{
_in = new BufferedInputStream(in);
_contentType = contentType;
_config = config;
_contextTmpDir = contextTmpDir;
if (_contextTmpDir == null)
_contextTmpDir = new File (System.getProperty("java.io.tmpdir"));
if (_config == null)
_config = new MultipartConfigElement(_contextTmpDir.getAbsolutePath());
}
public Collection getParts()
throws IOException, ServletException
{
parse();
Collection