commons-fileupload框架源码解析(八)--DeferredFileOutputStream

  1. commons-fileupload框架源码解析(一)--实例
  2. commons-fileupload框架源码解析(二)--HTTP
  3. commons-fileupload框架源码解析(三)--ParseRequest
  4. commons-fileupload框架源码解析(四)--FileItemIterator
  5. commons-fileupload框架源码解析(五)--MultipartStream
  6. commons-fileupload框架源码解析(六)--ParameterParser
  7. commons-fileupload框架源码解析(七)--FileCleaningTracker
  8. commons-fileupload框架源码解析(八)--DeferredFileOutputStream

简介

DeferredFileOutputStream是一个根据设定的最大内存阀值去控制写入到内存中,还是写入到硬盘中。

ThresholdingOutputStream

DeferredFileOutputStream继承ThresholdOutputStream,ThresholdOutputStream继承OuptStream,重写了write相关方法。

ThresholdOutputStream.write相关方法

 @Override
    public void write(final int b) throws IOException
    {
        checkThreshold(1);
        getStream().write(b);
        written++;
    }

    @Override
    public void write(final byte b[]) throws IOException
    {
        checkThreshold(b.length);
        getStream().write(b);
        written += b.length;
    }

  @Override
    public void write(final byte b[], final int off, final int len) throws IOException
    {
        checkThreshold(len);
        getStream().write(b, off, len);
        written += len;
    }

主要是加上了chekThreshold(len)方法,并调用getStream()交给另一个流
处理,并统计写入了多少字节(written)。

ThresholdOutputStream.checkThreshold(int)

protected void checkThreshold(final int count) throws IOException
    {
        if (!thresholdExceeded && written + count > threshold)
        {
            thresholdExceeded = true;
            thresholdReached();
        }
    }

检查当前的写入到内容流的字节数written是否大于阀值threshold,大于的时候会调用thresholdReached()

getStream & thresholdReached

/**
     * Returns the underlying output stream, to which the corresponding
     * OutputStream methods in this class will ultimately delegate.
     * 获取输出流
     * @return The underlying output stream.
     *
     * @throws IOException if an error occurs.
     */
    protected abstract OutputStream getStream() throws IOException;


    /**
     * Indicates that the configured threshold has been reached, and that a
     * subclass should take whatever action necessary on this event. This may
     * include changing the underlying output stream.
     * 当前的写入字节数written是否大于阀值threshold时触发
     * @throws IOException if an error occurs.
     */
    protected abstract void thresholdReached() throws IOException;

这两个是抽象方法,而DeferredFileOutputStream重写了,先看getStream

DeferredFileOutputStream.getStream

  @Override
    protected OutputStream getStream() throws IOException
    {
        return currentOutputStream;
    }

返回currentOuputStream,一开始默认是内存流ByteArrayOutputStream。

DeferredFileOutputStream.thresholdReached

@Override
    protected void thresholdReached() throws IOException
    {
        //如果prefix,suffix,directory不为null,outputFile不管是否已经引用了对象,都会重新调用File.createTempFile(String,String,File)来
        //创建指定的临时文件,并让后outputFile指向这个文件
        if (prefix != null) {
            //创建临时文件
            outputFile = File.createTempFile(prefix, suffix, directory);
        }
        FileUtils.forceMkdirParent(outputFile);//检查父级目录是否存在,不存在则创建,创建父级文件目录
        final FileOutputStream fos = new FileOutputStream(outputFile);
        try {
            memoryOutputStream.writeTo(fos);//将已经内容流的数据写入进文件流
        } catch (final IOException e){
            fos.close();//当前出现异常时关闭流,并抛出异常
            throw e;
        }
        currentOutputStream = fos;
        memoryOutputStream = null;
    }

当达到阀值的时候,thresholdReached()就会被调用,会将内存流memoryOutputStream中的数据转换到写入硬盘的流FileOuputStream中,并将FileOuputStream重新赋值currentOuptputStream

你可能感兴趣的:(commons-fileupload框架源码解析(八)--DeferredFileOutputStream)