📄 multipartstream.java
字号:
/*
* MultipartStream.java
*
* Created on 2004年12月28日, 上午12:24
* 这是一个用于上传文件的底层处理类。
*
*/
package com.mg.admin;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
/**
* 这是一个用于上传文件的底层处理类。
*
* <p>使用方法如下:<p>
* <pre>
* try {
* MultipartStream multipartStream = new MultipartStream(input,
* boundary);
* boolean nextPart = malitPartStream.skipPreamble();
* OutputStream output;
* while(nextPart) {
* // 处理头部
* header = chunks.readHeader();
* // 读取正文
* multipartStream.readBodyPart(output);
* nextPart = multipartStream.readBoundary();
* }
* } catch(MultipartStream.MalformedStreamException e) {
* // 数据不符合定义
* } catch(IOException) {
* // 读写错误
* }
*
* </pre>
*/
public class MultipartStream {
// ----------------------------------------------------- Manifest常量定义
/**
* 在<code>header-part</code>部分定义的最大处理长度
* (10 kilobytes = 10240 bytes.)。
*/
public static final int HEADER_PART_SIZE_MAX = 10240;
/**
* 缺省的缓冲大小。
*/
protected static final int DEFAULT_BUFSIZE = 4096;
/**
* 以字节顺序定义的<code>header-part</code>标志
* (<code>CRLFCRLF</code>)。
*/
protected static final byte[] HEADER_SEPARATOR = {0x0D, 0x0A, 0x0D, 0x0A};
/**
* 以字节顺序表示的在包后面用到的定界符(<code>CRLF</code>)。
*/
protected static final byte[] FIELD_SEPARATOR = { 0x0D, 0x0A };
/**
* 以字节顺序定义的流中的定界符(<code>--</code>)。
*/
protected static final byte[] STREAM_TERMINATOR = { 0x2D, 0x2D };
// ----------------------------------------------------------- 数据成员
/**
* 读取字符的输入流。
*/
private InputStream input;
/**
* 边界标识的长度。
*/
private int boundaryLength;
/**
* 要在缓冲中保留的,为了测试定界符的,以字节形式的数据的大小。
*/
private int keepRegion;
/**
* 边界数组。
*/
private byte[] boundary;
/**
* 用来处理request请求的缓冲大小。
*/
private int bufSize;
/**
* 用来处理request请求的缓冲。
*/
private byte[] buffer;
/**
* 在缓冲中第一个有效的字符索引。
* <br>
* 0 <= head < bufSize
*/
private int head;
/**
* 在buffer + 1缓冲中最后一个有效字符的索引。
* <br>
* 0 <= tail <= bufSize
*/
private int tail;
/**
* 内容的编码方式。
*/
private String headerEncoding;
// ----------------------------------------------------------- Constructors
/**
* 缺省的构造函数。
*
* @see #MultipartStream(InputStream, byte[], int)
* @see #MultipartStream(InputStream, byte[])
*
*/
public MultipartStream() {
}
/**
* 构造函数
*
* @param input 输入流
* @param boundary 边界标识
* @param bufSize 缓冲大小
*
*
* @see #MultipartStream()
* @see #MultipartStream(InputStream, byte[])
*
*/
public MultipartStream(InputStream input,
byte[] boundary,
int bufSize) {
this.input = input;
this.bufSize = bufSize;
this.buffer = new byte[bufSize];
this.boundary = new byte[boundary.length + 4];
this.boundaryLength = boundary.length + 4;
this.keepRegion = boundary.length + 3;
this.boundary[0] = 0x0D;
this.boundary[1] = 0x0A;
this.boundary[2] = 0x2D;
this.boundary[3] = 0x2D;
System.arraycopy(boundary, 0, this.boundary, 4, boundary.length);
head = 0;
tail = 0;
}
/**
* 构造函
* <p>
* @param input 输入流
* @param boundary 边界标识
*
*
* @see #MultipartStream()
* @see #MultipartStream(InputStream, byte[], int)
*
*/
public MultipartStream(InputStream input,
byte[] boundary)
throws IOException {
this(input, boundary, DEFAULT_BUFSIZE);
}
// --------------------------------------------------------- 公共方法
/**
* 返回头部的编码格式,如果没有指定编码格式,则使用缺省的编码。
*
*
* @return 返回头部的编码格式
*/
public String getHeaderEncoding() {
return headerEncoding;
}
/**
* 设置头部的编码格式,如果没有指定编码格式,则使用缺省的编码
*
* @param encoding 要设置的编码格式
*/
public void setHeaderEncoding(String encoding) {
headerEncoding = encoding;
}
/**
* 从缓冲中读取一个字节
*
* @return 返回下一个字节
*/
public byte readByte()
throws IOException {
// Buffer使用完了吗 ?
if (head == tail) {
head = 0;
// Refill.
tail = input.read(buffer, head, bufSize);
if (tail == -1) {
// 没有更多的数据了
throw new IOException("No more data is available");
}
}
return buffer[head++];
}
/**
* 跳过边界标识,是否有更多的<code>encapsulations</code>包含在缓冲中。
*
* @return 如果在缓冲中还有包就返回<code>true</code>,否则返回false。
*
*/
public boolean readBoundary()
throws MalformedStreamException {
byte[] marker = new byte[2];
boolean nextChunk = false;
head += boundaryLength;
try {
marker[0] = readByte();
marker[1] = readByte();
if (arrayequals(marker, STREAM_TERMINATOR, 2)) {
nextChunk = false;
} else if (arrayequals(marker, FIELD_SEPARATOR, 2)) {
nextChunk = true;
} else {
throw new MalformedStreamException(
"Unexpected characters follow a boundary");
}
} catch (IOException e) {
throw new MalformedStreamException("Stream ended unexpectedly");
}
return nextChunk;
}
/**
* <p>设置边界符
*
* @param 设置边界符号
*
*/
public void setBoundary(byte[] boundary)
throws IllegalBoundaryException {
if (boundary.length != boundaryLength - 4) {
throw new IllegalBoundaryException(
"The length of a boundary token can not be changed");
}
System.arraycopy(boundary, 0, this.boundary, 4, boundary.length);
}
/**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -