2021SC@SDUSC【软件工程应用与实践】Cocoon项目7——core文件夹分析(6)

2021SC@SDUSC

part.java

1、总结

继承自object
实现了Disposable接口

这个抽象类表示从 http post 流解析的文件部分。根据web.xml 中的上传配置决定使用的具体类 PartOnDiskPartInMemory

如果上传的数据大小超过允许的最大上传大小(也在 web.xml 中指定),则使用 RejectedPart,虽然无法从中获取数据,但会提供有关被拒绝上传的一些信息

2、主要属性

//字段标题
protected Map headers;

3、方法

public Map getHeaders()
  • 返回字段标题
public abstract int getSize()
  • 返回文件内容的长度
public boolean isRejected() 
  • 判断该部分是否为被拒绝的部分,并在不方便的地方(例如 flowscript)提供作为 RejectedPart 实例的替代方案
  • 如果这部分被拒绝,则返回 true
public String getMimeType()
  • 返回mime类型(如果未知,则返回 null)
public boolean disposeWithRequest()
  • 当创建它的请求处理完成时,是否希望清除此部分持有的任何临时资源? 默认为true
  • 如果该部件应与请求一起处理,则返回 true
public void setDisposeWithRequest(boolean dispose)
  • 设置 disposeWithRequest 标志的值(默认为 true)
  • 参数dispose——如果零件应在请求处理后处理,则为 true
public abstract InputStream getInputStream()
  • 返回包含文件数据的输入流
public void copyToSource(ModifiableSource source) throws IOException
  • 将零件复制到可修改源的便捷方法
  • 参数source——要写入的可修改源
public void copyToFile(String filename) throws IOException
  • 将零件复制到文件的便捷方法
  • 参数filename——要写入的文件的名称
public abstract void dispose()
  • 处置此部分持有的任何资源,例如文件或内存缓冲区
  • 当部件被垃圾收集时,在所有情况下都会发生处置,但明确调用它可以更快地清理资源

4、其他

补充:disposable接口

  1. 当组件需要在销毁之前释放和处置资源时使用 Disposable 接口
  2. 在组件生命周期结束时调用 dispose ()。 此方法将在 Startable.stop() 方法之后调用(如果由组件实现),组件使用此方法来释放和销毁组件拥有的任何资源

PartOnDisk.java

1、总结

继承自Part

此类表示从 http post 流解析的文件部分

2、方法

public String getFileName()
  • 返回文件名
public int getSize()
  • 以字节为单位返回文件大小
public InputStream getInputStream() throws IOException
  • 返回包含文件数据的 (ByteArray)输入流
public void dispose()
  • 清理保存部分数据的字节数组内容缓冲区
public void finalize() throws Throwable
  • 调用dispose(),确保底层文件已被删除

RejectedPart.java

1、总结

由于请求长度超过最大上传大小而被拒绝的上传部分

继承自Part

2、方法

public int getSize()
  • 获取该部分的大小
public int getMaxContentLength()
  • 获取允许的最大上传大小。 这并不适用于完整的请求内容长度,包括多部分边界和其他表单数据值
  • 这意味着上传部分可以被拒绝,尽管它的单个大小(一比特)小于最大大小。 因此,建议使用 getContentLength() 而不是 getSize() 来构建错误消息
public int getContentLength()
  • 获取导致这部分被拒绝的请求的内容长度(以字节为单位)
public boolean isRejected()
  • 判断该部分是否为被拒绝的部分
public void dispose()
  • 处置此部分持有的任何资源,例如文件或内存缓冲区

TokenStream.java

1、总结

MultipartParser 的实用程序类,将输入分成由给定边界分隔的部分,在每个边界之后都会有一个换行符并被解析

继承自PushbackInputStream

2、组要属性

//初始状态,未设置边界
public static final int STATE_NOBOUNDARY = -1;
//完整阅读一个部分,现在在一个新部分的开始
public static final int STATE_NEXTPART = -2;
//读取最后一个边界,多部分块的结尾
public static final int STATE_ENDMULTIPART = -3;
//流结束,这不应该发生,常用作安全检查
public static final int STATE_ENDOFSTREAM = -4;
//目前正在阅读一部分
public static final int STATE_READING = -5;

3、方法

public TokenStream(PushbackInputStream in)
  • 从 in 创建一个新的推回令牌流
  • 参数in:输入流
public TokenStream(PushbackInputStream in, int size)
  • 从 in 创建一个新的推回令牌流
  • 参数size:回推缓冲区的大小(以字节为单位)
public void setBoundary(byte[] boundary) throws MultipartException
  • 设置要扫描的边界
  • 参数boundary:包含边界的字节数组
public void nextPart() throws MultipartException
  • 开始阅读流中的下一部分,仅当 state 为 STATE_NEXTPART 时才可以调用此方法。 它会抛出一个 MultipartExceptio
private int readToBoundary(byte[] out) throws IOException
  • 填充输出缓冲区,直到它已满、已到达边界或已到达输入流的末尾
  • 当到达边界时,它会被完全读取,包括尾随的 \r 和 \n
  • 它不会被写入输出缓冲区,每次调用后都会更新流状态

具体方法如下:

private int readToBoundary(byte[] out) throws IOException {
        if (state != STATE_READING) {
            return 0;}
        int boundaryIndex = 0;
        int written = 0;
        int b = in.read();
        while (true) {
            while ((byte) b != boundary[0]) {
                if (b == -1) {
                    state = STATE_ENDOFSTREAM;
                    return written;
                }
                out[written++] = (byte) b;
                if (written == out.length) {
                    return written; }
                b = in.read(); }
            // 匹配第一个字节
            boundaryIndex = 0;                       
            // 检查边界
            while ((boundaryIndex < boundary.length)
                    && ((byte) b == boundary[boundaryIndex])) {
                b = in.read();
                boundaryIndex++;}
            if (boundaryIndex == boundary.length) {    // 匹配边界
                if (b != -1) {
                    if (b == '\r') {                   // 换行,另一部分如下 
                        state = STATE_NEXTPART;
                        in.read();
                    } else if (b == '-') {             // 连字符,多部分结束
                        state = STATE_ENDMULTIPART;
                        in.read();                     // 读取下一个连字符
                        in.read();                     // 读取\r
                        in.read();                     // 读取\n
                    } else {                           // 其他情况则报错
                        throw new IOException(
                                "Unexpected character after boundary");
                    }
                } else {    // 边界后什么也没有,不应该发生
                    state = STATE_ENDOFSTREAM;}
                return written;
            }
            // 不匹配边界
            // 字节跳过,写入第一个跳过的字节,推回其余的字节
            if (b != -1) {                         // b可能为-1
                in.unread(b);                      // 不匹配的字节
            }
            in.unread(boundary, 1,
                    boundaryIndex - 1);          // 不读取跳过边界数据
            out[written++] = boundary[0];
            if (written == out.length) {
                return written;}
            b = in.read();
        }
    }

补充:read()
从此输入流中读取下一个数据字节。
值字节以int类型返回,范围为0-255。如果因为流的末尾已到达而没有可用的字节,则该值返回-1。
此方法直到输入数据可用、检测到流结束或抛出异常为止才会阻塞。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值