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 点击打开链接
阅读全文
0 0
- Java 文件上传 JQ 文件上传
- java文件上传原理
- java文件上传原理
- java上传文件
- 上传文件 JSP+java
- JAVA上传文件
- java上传文件
- java fileupload上传文件
- java-文件上传案例
- JAVA上传EXCEL文件
- java上传文件
- java 超大文件上传
- java上传文件实例
- java 文件上传
- JAVA 上传文件类
- JAVA之"文件上传"
- java文件上传
- java文件上传方法
- 加载配置文件出错
- 《刻意练习》读书笔记
- JVM内存组成
- POJ 3764 The xor-longest Path Trie树/字典树
- 音频和视频处理 6
- java文件上传
- RQNOJ 117 最佳课题选择
- PHP开发API
- Redis初探&基本命令(一)
- 数字图像学习笔记
- win8全角/半角切换
- 日期和时间命令使用
- 吸顶菜单和置顶菜单
- PP代码生成器(三) 设计freemarker模板, 创建解决方案