java文件上传

来源:互联网 发布:mix软件是什么 编辑:程序博客网 时间:2024/06/15 12:46

大概的协议格式为:

头呢有酱婶的信息:[注:${bound}这个是边界占位符会在body用到]

Content-Type: multipart/form-data; boundary=${bound}    

multipart/form-data body呢大概是酱婶的:

--${bound}  Content-Disposition: form-data; name="Filename"    HTTP.pdf  --${bound}  Content-Disposition: form-data; name="file000"; filename="HTTP协议详解.pdf"  Content-Type: application/octet-stream    %PDF-1.5  file content  %%EOF  --${bound}  Content-Disposition: form-data; name="Upload"    Submit Query  --${bound}--  

no picture say ge j8? 上栗子

Content-Type:
multipart/form-data; boundary=----WebKitFormBoundaryqao1oDQOjWcGVMoa


更有说服力的源码上场了:

commons-fileupload源码是酱婶说的:

public List parseRequest(RequestContext ctx) throws FileUploadException {        List items = new ArrayList();        boolean successful = false;        boolean var21 = false;        FileItem fileItem;        ArrayList var29;        try {            var21 = true;            FileItemIterator iter = this.getItemIterator(ctx);            FileItemFactory fac = this.getFileItemFactory();            if(fac == null) {                throw new NullPointerException("No FileItemFactory has been set.");            }            while(true) {                if(!iter.hasNext()) {                    successful = true;                    var29 = items;                    var21 = false;                    break;                }                FileItemStream item = iter.next();                String fileName = ((FileUploadBase.FileItemIteratorImpl.FileItemStreamImpl)item).name;                fileItem = fac.createItem(item.getFieldName(), item.getContentType(), item.isFormField(), fileName);                items.add(fileItem);                try {                    Streams.copy(item.openStream(), fileItem.getOutputStream(), true);                } catch (FileUploadBase.FileUploadIOException var24) {                    throw (FileUploadException)var24.getCause();                } catch (IOException var25) {                    throw new FileUploadBase.IOFileUploadException("Processing of multipart/form-data request failed. " + var25.getMessage(), var25);                }                if(fileItem instanceof FileItemHeadersSupport) {                    FileItemHeaders fih = item.getHeaders();                    ((FileItemHeadersSupport)fileItem).setHeaders(fih);                }            }        } catch (FileUploadBase.FileUploadIOException var26) {            throw (FileUploadException)var26.getCause();        } catch (IOException var27) {            throw new FileUploadException(var27.getMessage(), var27);        } finally {            if(var21) {                if(!successful) {                    Iterator iterator = items.iterator();                    while(iterator.hasNext()) {                        FileItem fileItem = (FileItem)iterator.next();                        try {                            fileItem.delete();                        } catch (Throwable var22) {                            ;                        }                    }                }            }        }        if(!successful) {            Iterator iterator = items.iterator();            while(iterator.hasNext()) {                fileItem = (FileItem)iterator.next();                try {                    fileItem.delete();                } catch (Throwable var23) {                    ;                }            }        }        return var29;    }
根据parseRequest方法中的Streams.copy(item.openStream(), fileItem.getOutputStream(), true);
得知FileItemIterator 生出的 FileItemStream 和 怎么生的是我们关注的地方:

FileItemIterator:
FileItemIteratorImpl(RequestContext ctx) throws FileUploadException, IOException {            if(ctx == null) {                throw new NullPointerException("ctx parameter");            } else {                String contentType = ctx.getContentType();                if(null != contentType && contentType.toLowerCase().startsWith("multipart/")) {                    InputStream input = ctx.getInputStream();                    if(FileUploadBase.this.sizeMax >= 0L) {                        int requestSize = ctx.getContentLength();                        if(requestSize == -1) {                            input = new LimitedInputStream((InputStream)input, FileUploadBase.this.sizeMax) {                                protected void raiseError(long pSizeMax, long pCount) throws IOException {                                    FileUploadException ex = new FileUploadBase.SizeLimitExceededException("the request was rejected because its size (" + pCount + ") exceeds the configured maximum" + " (" + pSizeMax + ")", pCount, pSizeMax);                                    throw new FileUploadBase.FileUploadIOException(ex);                                }                            };                        } else if(FileUploadBase.this.sizeMax >= 0L && (long)requestSize > FileUploadBase.this.sizeMax) {                            throw new FileUploadBase.SizeLimitExceededException("the request was rejected because its size (" + requestSize + ") exceeds the configured maximum (" + FileUploadBase.this.sizeMax + ")", (long)requestSize, FileUploadBase.this.sizeMax);                        }                    }                    String charEncoding = FileUploadBase.this.headerEncoding;                    if(charEncoding == null) {                        charEncoding = ctx.getCharacterEncoding();                    }                    this.boundary = FileUploadBase.this.getBoundary(contentType);                    if(this.boundary == null) {                        throw new FileUploadException("the request was rejected because no multipart boundary was found");                    } else {                        this.notifier = new ProgressNotifier(FileUploadBase.this.listener, (long)ctx.getContentLength());                        this.multi = new MultipartStream((InputStream)input, this.boundary, this.notifier);                        this.multi.setHeaderEncoding(charEncoding);                        this.skipPreamble = true;                        this.findNextItem();                    }                } else {                    throw new FileUploadBase.InvalidContentTypeException("the request doesn't contain a multipart/form-data or multipart/mixed stream, content type header is " + contentType);                }            }        }

呜呜喳喳一大堆,发现了这个:MultipartStream构造如下:
this.input = input;        this.bufSize = bufSize;        this.buffer = new byte[bufSize];        this.notifier = pNotifier;        this.boundary = new byte[boundary.length + BOUNDARY_PREFIX.length];        this.boundaryLength = boundary.length + BOUNDARY_PREFIX.length;        this.keepRegion = this.boundary.length;        System.arraycopy(BOUNDARY_PREFIX, 0, this.boundary, 0, BOUNDARY_PREFIX.length);        System.arraycopy(boundary, 0, this.boundary, BOUNDARY_PREFIX.length, boundary.length);        this.head = 0;        this.tail = 0;
很显然boundary被保留起来了;

在FileItemStream中发现:

FileItemStreamImpl(String pName, String pFieldName, String pContentType, boolean pFormField, long pContentLength) throws IOException {                this.name = pName;                this.fieldName = pFieldName;                this.contentType = pContentType;                this.formField = pFormField;                final ItemInputStream itemStream = FileItemIteratorImpl.this.multi.newInputStream();                InputStream istream = itemStream;                if(FileUploadBase.this.fileSizeMax != -1L) {                    if(pContentLength != -1L && pContentLength > FileUploadBase.this.fileSizeMax) {                        FileUploadBase.FileSizeLimitExceededException e = new FileUploadBase.FileSizeLimitExceededException("The field " + this.fieldName + " exceeds its maximum permitted " + " size of " + FileUploadBase.this.fileSizeMax + " bytes.", pContentLength, FileUploadBase.this.fileSizeMax);                        e.setFileName(pName);                        e.setFieldName(pFieldName);                        throw new FileUploadBase.FileUploadIOException(e);                    }                    istream = new LimitedInputStream(itemStream, FileUploadBase.this.fileSizeMax) {                        protected void raiseError(long pSizeMax, long pCount) throws IOException {                            itemStream.close(true);                            FileUploadBase.FileSizeLimitExceededException e = new FileUploadBase.FileSizeLimitExceededException("The field " + FileItemStreamImpl.this.fieldName + " exceeds its maximum permitted " + " size of " + pSizeMax + " bytes.", pCount, pSizeMax);                            e.setFieldName(FileItemStreamImpl.this.fieldName);                            e.setFileName(FileItemStreamImpl.this.name);                            throw new FileUploadBase.FileUploadIOException(e);                        }                    };                }                this.stream = (InputStream)istream;            }
MultipartStream.ItemInputStream newInputStream() {    return new MultipartStream.ItemInputStream();}

multi也就是MultipartStream被用来开流了,MultipartStream又用到了ItemInputStream

以下部分开始处理那body里的数据了,反正看起来很厉害的样子。

ItemInputStream() {            this.findSeparator();        }        private void findSeparator() {            this.pos = MultipartStream.this.findSeparator();            if(this.pos == -1) {                if(MultipartStream.this.tail - MultipartStream.this.head > MultipartStream.this.keepRegion) {                    this.pad = MultipartStream.this.keepRegion;                } else {                    this.pad = MultipartStream.this.tail - MultipartStream.this.head;                }            }        }
public int available() throws IOException {            return this.pos == -1?MultipartStream.this.tail - MultipartStream.this.head - this.pad:this.pos - MultipartStream.this.head;        }        public int read() throws IOException {            if(this.closed) {                throw new ItemSkippedException();            } else if(this.available() == 0 && this.makeAvailable() == 0) {                return -1;            } else {                ++this.total;                int b = MultipartStream.this.buffer[MultipartStream.this.head++];                return b >= 0?b:b + 256;            }        }        public int read(byte[] b, int off, int len) throws IOException {            if(this.closed) {                throw new ItemSkippedException();            } else if(len == 0) {                return 0;            } else {                int res = this.available();                if(res == 0) {                    res = this.makeAvailable();                    if(res == 0) {                        return -1;                    }                }                res = Math.min(res, len);                System.arraycopy(MultipartStream.this.buffer, MultipartStream.this.head, b, off, res);                MultipartStream.this.head = res;                this.total += (long)res;                return res;            }        }

private int makeAvailable() throws IOException {            if(this.pos != -1) {                return 0;            } else {                this.total += (long)(MultipartStream.this.tail - MultipartStream.this.head - this.pad);                System.arraycopy(MultipartStream.this.buffer, MultipartStream.this.tail - this.pad, MultipartStream.this.buffer, 0, this.pad);                MultipartStream.this.head = 0;                MultipartStream.this.tail = this.pad;                int av;                do {                    int bytesRead = MultipartStream.this.input.read(MultipartStream.this.buffer, MultipartStream.this.tail, MultipartStream.this.bufSize - MultipartStream.this.tail);                    if(bytesRead == -1) {                        String msg = "Stream ended unexpectedly";                        throw new MultipartStream.MalformedStreamException("Stream ended unexpectedly");                    }                    if(MultipartStream.this.notifier != null) {                        MultipartStream.this.notifier.noteBytesRead(bytesRead);                    }                    MultipartStream.this.tail = bytesRead;                    this.findSeparator();                    av = this.available();                } while(av <= 0 && this.pos == -1);                return av;            }        }
基本完成只能说666...

spring:

servlet:



未完待续...

参考:(请以协议为准,其他资料仅供参考)

http1.1协议 点击打开链接 点击打开链接 点击打开链接 点击打开链接

百度http协议点击打开链接

spring-multipart API 点击打开链接

servlet3.0 点击打开链接

fileupload 点击打开链接 点击打开链接 点击打开链接

单文件servlet API 点击打开链接 点击打开链接 点击打开链接

http multipart 点击打开链接