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

📄 multipartboundaryinputstream.java

📁 jakarta-struts-1.2.4-src
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * $Header: /home/cvs/jakarta-struts/src/share/org/apache/struts/upload/MultipartBoundaryInputStream.java,v 1.6 2004/03/14 06:23:48 sraeburn Exp $
 * $Revision: 1.6 $
 * $Date: 2004/03/14 06:23:48 $
 *
 * Copyright 1999-2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

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.
 *
 *
 * @deprecated Use the Commons FileUpload based multipart handler instead. This
 *             class will be removed after Struts 1.2.
 */
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
    {
        fillLine();
        if (!this.boundaryEncountered)
        {
            throw new IOException(MESSAGE_INVALID_START);
        }
        fillLine();
        readElementHeaders();
    }

    private final void readElementHeaders() throws IOException
    {
        readContentDisposition();
        resetCrlf();
        boolean hadContentType = readContentType();
        resetCrlf();
        if (hadContentType)
        {
            skipCurrentLineIfBlank();
        }

⌨️ 快捷键说明

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