⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multipartboundaryinputstream.java

📁 这是一个轻便的j2ee的web应用框架,是一个在多个项目中运用的实际框架,采用struts,hebinate,xml等技术,有丰富的tag,role,navigation,session,dictio
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * $Header: /sfroot/cvs/esimple/src/core/org/apache/struts/upload/MultipartBoundaryInputStream.java,v 1.1.1.1 2004/09/08 06:38:41 lava Exp $
 * $Revision: 1.1.1.1 $
 * $Date: 2004/09/08 06:38:41 $
 *
 * ====================================================================
 *
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2002 The Apache Software Foundation.  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, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Struts", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 */

package org.apache.struts.upload;

import java.io.InputStream;
import java.io.IOException;
import java.io.File;

/**
 * This class encapsulates parsing functionality for RFC1867, multipart/form-data. See MultipartBoundaryInputStreamTest
 * and MultipartIterator for usage examples.
 *
 * @author Mike Schachter
 */
public class MultipartBoundaryInputStream extends InputStream
{
    private static final byte NEWLINE_BYTE = ((byte) '\n');

    private static final byte CARRIAGE_RETURN = ((byte) '\r');

    private static final byte[] CRLF = new byte[] {CARRIAGE_RETURN, NEWLINE_BYTE};

    private static final String DOUBLE_DASH_STRING = "--";

    private static final int DEFAULT_LINE_SIZE = 4096;

    private static final String TOKEN_EQUALS = "=";

    private static final char TOKEN_QUOTE = '\"';

    private static final char TOKEN_COLON = ':';

    private static final char TOKEN_SEMI_COLON = ';';

    private static final char TOKEN_SPACE = ' ';

    private static final String DEFAULT_CONTENT_DISPOSITION = "form-data";

    private static final String PARAMETER_NAME = "name";

    private static final String PARAMETER_FILENAME = "filename";

    private static final String PARAMETER_CHARSET = "charset";

    private static final String CONTENT_TYPE_TEXT_PLAIN = "text/plain";

    private static final String CONTENT_TYPE_APPLICATION_OCTET_STREAM = "application/octet-stream";

    private static final String MESSAGE_INVALID_START = "Multipart data doesn't start with boundary";

    /**
     * The InputStream to read from.
     */
    protected InputStream inputStream;

    /**
     * The boundary.
     */
    protected String boundary;

    /**
     * Whether or not the boundary has been encountered.
     */
    protected boolean boundaryEncountered;

    /**
     * Whether or not the final boundary has been encountered.
     */
    protected boolean finalBoundaryEncountered;

    /**
     * Whether or not the end of the stream has been read.
     */
    protected boolean endOfStream;

    /**
     * The Content-Disposition for the current form element being read.
     */
    protected String elementContentDisposition;

    /**
     * The name of the current form element being read.
     */
    protected String elementName;

    /**
     * The Content-Type of the current form element being read.
     */
    protected String elementContentType;

    /**
     * The filename of the current form element being read, <code>null</code> if the current form element is
     * text data.
     */
    protected String elementFileName;

    /**
     * The character encoding of the element, specified in the element's Content-Type header.
     */
    protected String elementCharset;

    /**
     * The maximum length in bytes to read from the stream at a time, or -1 for unlimited length.
     */
    protected long maxLength;

    /**
     * Whether or not the maximum length has been met.
     */
    protected boolean maxLengthMet;

    /**
     * The total number of bytes read so far.
     */
    protected long bytesRead;

    private byte[] boundaryBytes;

    private byte[] finalBoundaryBytes;

    private byte[] line;

    private int lineSize;

    private int lineLength;

    private boolean lineHasNewline;

    private boolean lineHasCarriage;

    private int lineIndex;

    public MultipartBoundaryInputStream()
    {
        this.lineSize  = DEFAULT_LINE_SIZE;
        this.maxLength = -1;
        resetStream();
    }

    /**
     * Sets the boundary that terminates the data for the stream, after adding the prefix "--"
     */
    public void setBoundary(String boundary)
    {
        this.boundary           = DOUBLE_DASH_STRING + boundary;
        this.boundaryBytes      = this.boundary.getBytes();
        this.finalBoundaryBytes = (this.boundary + DOUBLE_DASH_STRING).getBytes();
    }

    /**
     * Resets this stream for use with the next element, to be used after a boundary is encountered.
     */
    public void resetForNextBoundary() throws IOException
    {
        if (!this.finalBoundaryEncountered)
        {
            this.boundaryEncountered = false;
            resetCrlf();
            fillLine();
            readElementHeaders();
        }
    }

    /**
     * Sets the input stream used to read multipart data. For efficiency purposes, make sure that the stream
     * you set on this class is buffered. The way this class reads lines is that it continually calls the read()
     * method until it reaches a newline character. That would be terrible if you were to set a socket's input stream
     * here, but not as bad on a buffered stream.
     */
    public void setInputStream(InputStream stream) throws IOException
    {
        this.inputStream = stream;
        resetStream();
        readFirstElement();
    }

    /**
     * Reads from the stream. Returns -1 if it's the end of the stream or if a boundary is encountered.
     */
    public int read() throws IOException
    {
        if (!this.maxLengthMet)
        {
            if (!this.boundaryEncountered)
            {
                return readFromLine();
            }
        }
        return -1;
    }

    public int read(byte[] buffer) throws IOException
    {
        return read(buffer, 0, buffer.length);
    }

    public int read(byte[] buffer, int offset, int length) throws IOException
    {
        if (length > 0)
        {
            int read = read();
            if ((read == -1) && (this.endOfStream || this.boundaryEncountered))
            {
                return -1;
            }
            int bytesRead = 1;
            buffer[offset++] = (byte) read;

            while ((bytesRead < length) && (((read = read())!= -1) || ((read == -1) &&
                    (!this.boundaryEncountered))) && !this.maxLengthMet)
            {
                buffer[offset++] = (byte) read;
                bytesRead++;
            }
            return bytesRead;
        }
        return -1;
    }

    /**
     * Marks the underlying stream.
     */
    public synchronized void mark(int i)
    {
        this.inputStream.mark(i);
    }

    /**
     * Resets the underlying input stream.
     */
    public synchronized void reset() throws IOException
    {
        this.inputStream.reset();
    }

    /**
     * Set the maximum length in bytes to read, or -1 for an unlimited length.
     */
    public void setMaxLength(long maxLength)
    {
        this.maxLength = maxLength;
    }

    public long getMaxLength()
    {
        return maxLength;
    }

    /**
     * Whether or not the maximum length has been met.
     */
    public boolean isMaxLengthMet()
    {
        return maxLengthMet;
    }

    /**
     * Gets the value for the "Content-Dispositio" header for the current multipart element.
     * Usually "form-data".
     */
    public String getElementContentDisposition()
    {
        return this.elementContentDisposition;
    }

    /**
     * Gets the name of the current element. The name corresponds to the value of
     * the "name" attribute of the form element.
     */
    public String getElementName()
    {
        return this.elementName;
    }

    /**
     * Gets the character encoding of the current element. The character encoding would have been specified
     * in the Content-Type header for this element, if it wasn't this is null.
     */
    public String getElementCharset()
    {
        return this.elementCharset;
    }

    /**
     * Gets the "Content-Type" of the current element. If this is a text element,
     * the content type will probably be "text/plain", otherwise it will be the
     * content type of the file element.
     */
    public String getElementContentType()
    {
        return this.elementContentType;
    }

    /**
     * Gets the filename of the current element, which will be null if the current element
     * isn't a file.
     */
    public String getElementFileName()
    {
        return this.elementFileName;
    }

    /**
     * Gets whether or not the current form element being read is a file.
     */
    public boolean isElementFile()
    {
        return (this.elementFileName != null);
    }

    /**
     * Returns whether or not the boundary has been encountered while reading data.
     */
    public boolean isBoundaryEncountered()
    {
        return this.boundaryEncountered;
    }

    /**
     * Returns whether or not the final boundary has been encountered.
     */
    public boolean isFinalBoundaryEncountered()
    {
        return this.finalBoundaryEncountered;
    }

    /**
     * Whether or not an EOF has been read on the stream.
     */
    public boolean isEndOfStream()
    {
        return this.endOfStream;
    }

    public void setLineSize(int size)
    {
        this.lineSize = size;
    }

    public long getBytesRead()
    {
        return this.bytesRead;
    }

    private final void readFirstElement() throws IOException

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -