文件上传原理实现

文件上传原理实现

客户端浏览器是怎样上传数据的呢?服务器端如何接收上传的文件数据?

级别: 初级

王延成 (王延成), 作者/编者, 

2004 年 9 月 01 日

文章主要描述http表单上传二进制数据流规范的简单实现

(一)关于Form表单上传文件规范

  总结个人在对新技术、新事物的学习和解决问题的过程,深刻体会到多理解掌握技术基础理论知识再加上相应的实践,的确能帮助我们在解决某些问题的时候起到事半功倍的效果。

以前上传文件类似的功能都是采用第三方组件来做的,真的是基于接口编程了。不出问题还好,真要是出现问题解决起来太不舒服了,往往属于那种拆了西墙补东墙的策略。最近,在做文件上传时学习了一些 关于html>form上传数据的格式规范,依据人家定义的规范做了一些简单的工作。。。算是实现了个小轮子吧。


(二)实现

1、规则
1.1 上传数据块的分割规则

基于html form表单上传的数据都是以类似-----------------------------7da3c8e180752{0x130x10}这样的分割符来标记一块数据的起止,可不要忘记后面的两个换行符。关于换行符有三种,如下:

操作系统换行符描述原始标记ascii码十六进制
WindowWindow的换行符是两个//r//n13100x0d0x0a
UnixUnix的换行符是一个//n100x0a
Mac OSMac OS的换行符是一个//r130x0d
这块没有对Unix、MacOS上做测试,只在Window上测试了换行是两个(0x0d0x0a)
1.2 注意在后台从request中取得分割串少两个 --,在看下面的原始数据你会发现流的最后是以 --结束的。
1.3 上传的原始数据串,本来中文字符是乱码的。为了清晰一些使用字符集UTF-8转了下码。

 
  1. -----------------------------7da3c8e180752  
  2. Content-Disposition: form-data; name="fileData1"filename="C:/abcdef.log"  
  3. Content-Type: application/octet-stream  
  4.   
  5. HelloWorld  
  6. HelloWorld  
  7.   
  8. -----------------------------7da3c8e180752  
  9. Content-Disposition: form-data; name="fileData2"filename="C:/deleteThumb.bat"  
  10. Content-Type: application/octet-stream  
  11.   
  12. FOR %%a IN ( C: D: E: F: ) DO DEL /f/s/q/a %%a/Thumbs.db  
  13. -----------------------------7da3c8e180752  
  14. Content-Disposition: form-data; name="textAreaContent"  
  15.   
  16. HelloWorld  
  17. -----------------------------7da3c8e180752  
  18. Content-Disposition: form-data; name="id"  
  19.   
  20. 文件编码  
  21. -----------------------------7da3c8e180752  
  22. Content-Disposition: form-data; name="name"  
  23.   
  24. 文件名称  
  25. -----------------------------7da3c8e180752--  
1.4 小结

基于1.3小节可以非常容易总结归纳出html-->form元素内容。有两个文件类型元素,三个text元素(其中一个元素是textarea)

2、操作顺序流程描述



回页首

3、实现代码

需要明确注意的一个问题是关于request.getInputStream();获取请求体数据流不可用的问题,见示例代码: 
  1. /*我是这么认为的在获取流之前,已经通过第三方应用服务器相关对ServletRequest接口实现解析过流了,所以我们再次取请求流内容时会有问题。。在参与.NET设备与JavaWeb交互时也遇到过此类型的问题。*/  
  2. /*这就要求我们如果是自己解析request流内容数据,在解析之前不可以调用getParameter(String paramName)相关的需要用到解析流的行为方法。*/  
  3. /*以上仅个人理解、个人意见,如有不对请多多指正。*/  
  4. request.getParameter("USER_CODE");  
  5. InputStream ins = request.getInputStream();  
  6. byte[] buff = new byte[1024];  
  7. int count = -1;  
  8. while ((count = ins.read(buff))!=-1) {  
  9.     System.out.println(new String(buff,0, count, "UTF-8"));  
  10. }  

3.1、类图

3.2、代码内容

入口Servlet
  1. package org.ybygjy.web;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.Iterator;  
  5. import java.util.List;  
  6.   
  7. import javax.servlet.ServletException;  
  8. import javax.servlet.http.HttpServlet;  
  9. import javax.servlet.http.HttpServletRequest;  
  10. import javax.servlet.http.HttpServletResponse;  
  11.   
  12. import org.ybygjy.web.comp.FileItem;  
  13. import org.ybygjy.web.comp.FileMgrComp;  
  14. import org.ybygjy.web.utils.WrapperRequest;  
  15.   
  16. /** 
  17.  * 处理基于WebHttp的请求/响应 
  18.  * @author WangYanCheng 
  19.  * @version 2010-1-10 
  20.  */  
  21. public class Servlet extends HttpServlet {  
  22.     /** default serial */  
  23.     private static final long serialVersionUID = 1L;  
  24.   
  25.     /** 
  26.      * {@inheritDoc} 
  27.      */  
  28.     public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException,  
  29.         IOException {  
  30.         request.setCharacterEncoding("UTF-8");  
  31.         List<FileItem> fileItemArr = null;  
  32.         String contentType = request.getContentType();  
  33.         if (null != contentType && contentType.startsWith(WrapperRequest.ContentType.FORM_DATA.getType())) {  
  34.             fileItemArr = new FileMgrComp().doAnalyse(WrapperRequest.getInstance(request), response);  
  35.             for (Iterator<FileItem> iterator = fileItemArr.iterator(); iterator.hasNext();) {  
  36.                 System.out.println(iterator.next());  
  37.             }  
  38.         }  
  39.     }  
  40. }  
  
工具类


回页首
  1. package org.ybygjy.web.utils;  
  2.   
  3. import javax.servlet.http.HttpServletRequest;  
  4.   
  5. /** 
  6.  * RequestUtils 
  7.  * @author WangYanCheng 
  8.  * @version 2010-1-10 
  9.  */  
  10. public class WrapperRequest {  
  11.     /**ContentType*/  
  12.     public enum ContentType {  
  13.         /**MIME类型-二进制数据标记*/  
  14.         FORM_DATA("multipart/form-data"),  
  15.         /**MIME类型-标准编码格式标记*/  
  16.         FORM_URLENCODE("application/x-www-form-urlencoded"),  
  17.         /**MIME类型-文本格式标记*/  
  18.         FORM_TEXT("text/plain");  
  19.         /**inner type*/  
  20.         private final String type;  
  21.         /** 
  22.          * Constructor 
  23.          * @param str type 
  24.          */  
  25.         private ContentType(String str) {  
  26.             this.type = str;  
  27.         }  
  28.         /** 
  29.          * getter Type 
  30.          * @return type 
  31.          */  
  32.         public String getType() {  
  33.             return this.type;  
  34.         }  
  35.     }  
  36.     /**ContentType*/  
  37.     private String contentType;  
  38.     /**request*/  
  39.     private HttpServletRequest request = null;  
  40.     /** 
  41.      * Constructor 
  42.      * @param request request 
  43.      */  
  44.     private WrapperRequest(HttpServletRequest request) {  
  45.         this.request = request;  
  46.     }  
  47.     /** 
  48.      * getInstance 
  49.      * @param request request 
  50.      * @return wrapperRequest 
  51.      */  
  52.     public static final WrapperRequest getInstance(HttpServletRequest request) {  
  53.         return new WrapperRequest(request);  
  54.     }  
  55.     /** 
  56.      * get no wrapper Request 
  57.      * @return request request/null 
  58.      */  
  59.     public HttpServletRequest getRequest() {  
  60.         return this.request;  
  61.     }  
  62.     /** 
  63.      * getContentType 
  64.      * @return contentTypeStr/null 
  65.      */  
  66.     public String getContentType() {  
  67.         if (null == this.contentType) {  
  68.             this.contentType = null == this.request ? null : this.request.getContentType();  
  69.         }  
  70.         return this.contentType;  
  71.     }  
  72.     /** 
  73.      * 是否二制数据格式 
  74.      * @return true/false 
  75.      */  
  76.     public boolean isBinaryData() {  
  77.         boolean rtnBool = false;  
  78.         String tmpStr = getContentType();  
  79.         if (tmpStr.contains(ContentType.FORM_DATA.getType())) {  
  80.             rtnBool = true;  
  81.         }  
  82.         return rtnBool;  
  83.     }  
  84.     /** 
  85.      * 取得内容界定符 
  86.      * @return rtnStr/null 
  87.      */  
  88.     public String getBoundary() {  
  89.         String rtnStr = null;  
  90.         String tmpType = getContentType();  
  91.         if (null != tmpType) {  
  92.             rtnStr = tmpType.matches("^[//s//S]*boundary=[//s//S]*$") ? tmpType.split("boundary=")[1] : null;  
  93.         }  
  94.         return "--".concat(rtnStr);  
  95.     }  
  96.     /** 
  97.      * 测试入口 
  98.      * @param args 参数列表 
  99.      */  
  100.     public static void main(String[] args) {  
  101. //        WrapperRequest.ContentType[] cts = WrapperRequest.ContentType.values();  
  102. //        for (WrapperRequest.ContentType ct : cts) {  
  103. //            System.out.println(ct.getType());  
  104. //        }  
  105. //        System.out.println(WrapperRequest.getInstance(null).getBoundary());  
  106.         /*Matcher matcher = Pattern.compile("(//s)+").matcher("分/n/r割符"); 
  107.         while (matcher.find()) { 
  108.             int count = matcher.groupCount(); 
  109.             for (int i = 0; i < count; i++) { 
  110.                 byte[] tmpByte = matcher.group(i).getBytes(); 
  111.                 for (int tmpI : tmpByte) { 
  112.                     System.out.print(tmpI); 
  113.                 } 
  114.             } 
  115.         }*/  
  116.         WrapperRequest wpInst = WrapperRequest.getInstance(null);  
  117.         wpInst.getBoundary();  
  118.     }  
  119. }  
  
基础实现
  1. package org.ybygjy.web.comp;  
  2.   
  3. import java.io.BufferedOutputStream;  
  4. import java.io.File;  
  5. import java.io.FileOutputStream;  
  6. import java.io.IOException;  
  7. import java.io.InputStream;  
  8. import java.io.OutputStream;  
  9.   
  10. import org.ybygjy.web.utils.FileUtils;  
  11.   
  12. /** 
  13.  * 负责文件的存储解析 
  14.  * @author WangYanCheng 
  15.  * @version 2010-08-31 
  16.  */  
  17. public class FileItem {  
  18.     /** 源文件路径 */  
  19.     private String srcFilePath;  
  20.     /** 源文件全名称 */  
  21.     private String srcFileFullName;  
  22.     /** 源文件名称 */  
  23.     private String srcFileName;  
  24.     /** 文件转储路径 */  
  25.     private String filePath;  
  26.     /** 文件名称 */  
  27.     private String fileName;  
  28.     /** 文件全名称 */  
  29.     private String fileFullName;  
  30.     /** 上传文件参数名称 */  
  31.     private String paramName;  
  32.     /** MIME Type */  
  33.     private String mimeType;  
  34.     /** 分割串 */  
  35.     private String boundaryStr;  
  36.   
  37.     /** 
  38.      * Constructor 
  39.      * @param paramStr 参数名称 
  40.      * @param fileStr 源文件地址串 
  41.      * @param mimeType MIMEType 
  42.      * @param boundaryStr 分割约束 
  43.      */  
  44.     public FileItem(String paramStr, String fileStr, String mimeType, String boundaryStr) {  
  45.         String[] tmpStrArr = paramStr.split("=");  
  46.         this.setParamName(tmpStrArr[1].substring(1, tmpStrArr[1].length() - 1));  
  47.         tmpStrArr = fileStr.split("=");  
  48.         this.setSrcFilePath(tmpStrArr[1].substring(1, tmpStrArr[1].length() - 1));  
  49.         this.setMIME(mimeType);  
  50.         this.setBoundaryStr(boundaryStr);  
  51.     }  
  52.   
  53.     /** 
  54.      * setFilePath 
  55.      * @param filePath filePath 
  56.      */  
  57.     public void setSrcFilePath(String filePath) {  
  58.         this.srcFilePath = filePath;  
  59.         if (this.srcFilePath != null && filePath.length() > 0) {  
  60.             this.srcFileFullName = new File(this.srcFilePath).getName();  
  61.             this.srcFileName = this.srcFileFullName.substring(0this.srcFileFullName.indexOf('.'));  
  62.         }  
  63.     }  
  64.   
  65.     /** 
  66.      * setMIME 
  67.      * @param mimeType mimeType 
  68.      */  
  69.     public void setMIME(String mimeType) {  
  70.         this.mimeType = mimeType;  
  71.     }  
  72.   
  73.     /** 
  74.      * getMIME 
  75.      * @return mimeType mimeType 
  76.      */  
  77.     public String getMIME() {  
  78.         return this.mimeType;  
  79.     }  
  80.   
  81.     /** 
  82.      * setBoundary 
  83.      * @param boundaryStr the boundaryStr to set 
  84.      */  
  85.     public void setBoundaryStr(String boundaryStr) {  
  86.         this.boundaryStr = boundaryStr;  
  87.     }  
  88.   
  89.     /** 
  90.      * setParamName 
  91.      * @param paramName paramName 
  92.      */  
  93.     public void setParamName(String paramName) {  
  94.         this.paramName = paramName;  
  95.     }  
  96.   
  97.     /** 
  98.      * getParamName 
  99.      * @return paramName 
  100.      */  
  101.     public String getParamName() {  
  102.         return this.paramName;  
  103.     }  
  104.   
  105.     /** 
  106.      * 源上传文件全名称 
  107.      * @return the srcFileName 
  108.      */  
  109.     public String getSrcFileFullName() {  
  110.         return srcFileFullName == null ? null : srcFileFullName.length() == 0 ? null : this.srcFileFullName;  
  111.     }  
  112.   
  113.     /** 
  114.      * 源上传文件名称 
  115.      * @return the srcFileName 
  116.      */  
  117.     public String getSrcFileName() {  
  118.         return srcFileName;  
  119.     }  
  120.   
  121.     /** 
  122.      * 文件存储路径 
  123.      * @return the filePath 
  124.      */  
  125.     public String getFilePath() {  
  126.         return filePath;  
  127.     }  
  128.   
  129.     /** 
  130.      * 取文件名称 
  131.      * @return the fileName 
  132.      */  
  133.     public String getFileName() {  
  134.         return fileName;  
  135.     }  
  136.   
  137.     /** 
  138.      * 取文件全名称 
  139.      * @return the fileFullName 
  140.      */  
  141.     public String getFileFullName() {  
  142.         return fileFullName;  
  143.     }  
  144.   
  145.     /** 
  146.      * 转储文件 
  147.      * @param ins ins 
  148.      * @throws IOException IOException 
  149.      */  
  150.     public void doStoreFile(InputStream ins) throws IOException {  
  151.         String id = String.valueOf(System.currentTimeMillis());  
  152.         File tmpFile = new File(FileUtils.getTmpFilePath(), id);  
  153.         this.filePath = tmpFile.getPath();  
  154.         this.fileFullName = tmpFile.getName();  
  155.         this.fileName = id;  
  156.         BufferedOutputStream bos = null;  
  157.         try {  
  158.             bos = new BufferedOutputStream(new FileOutputStream(tmpFile));  
  159.             this.doStoreFile(ins, bos);  
  160.         } catch (IOException ioe) {  
  161.             throw ioe;  
  162.         } finally {  
  163.             try {  
  164.                 bos.close();  
  165.             } catch (IOException ioe) {  
  166.                 ioe.printStackTrace();  
  167.             }  
  168.         }  
  169.     }  
  170.   
  171.     /** 
  172.      * 存储文件 
  173.      * @param ins ins 
  174.      * @param bos bos 
  175.      * @throws IOException IOException 
  176.      */  
  177.     private void doStoreFile(InputStream ins, OutputStream bos) throws IOException {  
  178.         byte[] byteArr = new byte[this.boundaryStr.getBytes().length];  
  179.         try {  
  180.             int tmpI = -1;  
  181.             int tmpL = -1;  
  182.             ins.skip(2);  
  183.             while (((tmpI = ins.read()) != -1)) {  
  184.                 if (13 == tmpI) {  
  185.                     tmpL = ins.read();  
  186.                     if (10 == tmpL && isBoundary(ins, byteArr)) {  
  187.                         break;  
  188.                     } else {  
  189.                         bos.write(tmpI);  
  190.                         bos.write(tmpL);  
  191.                         if (10 == tmpL) {  
  192.                             bos.write(byteArr);  
  193.                         }  
  194.                         continue;  
  195.                     }  
  196.                 }  
  197.                 bos.write(tmpI);  
  198.             }  
  199.             bos.flush();  
  200.         } catch (IOException ioe) {  
  201.             throw ioe;  
  202.         }  
  203.     }  
  204.   
  205.     /** 
  206.      * 检验是否边界 
  207.      * @param ins ins 
  208.      * @param byteArr byteArr 
  209.      * @return true/false 
  210.      * @throws IOException IOException 
  211.      */  
  212.     private boolean isBoundary(InputStream ins, byte[] byteArr) throws IOException {  
  213.         if (null == this.boundaryStr) {  
  214.             return false;  
  215.         }  
  216.         boolean rtnFlag = false;  
  217.         int count = ins.read(byteArr);  
  218.         if (count != -1) {  
  219.             String str = new String(byteArr, 0, count);  
  220.             if (this.boundaryStr.equals(str)) {  
  221.                 rtnFlag = true;  
  222.             }  
  223.             byteArr = str.getBytes();  
  224.         }  
  225.         return rtnFlag;  
  226.     }  
  227.   
  228.     @Override  
  229.     public String toString() {  
  230.         StringBuilder builder = new StringBuilder();  
  231.         builder.append("FileItem [boundaryStr=");  
  232.         builder.append(boundaryStr);  
  233.         builder.append(", fileFullName=");  
  234.         builder.append(fileFullName);  
  235.         builder.append(", fileName=");  
  236.         builder.append(fileName);  
  237.         builder.append(", filePath=");  
  238.         builder.append(filePath);  
  239.         builder.append(", mimeType=");  
  240.         builder.append(mimeType);  
  241.         builder.append(", paramName=");  
  242.         builder.append(paramName);  
  243.         builder.append(", srcFileName=");  
  244.         builder.append(srcFileFullName);  
  245.         builder.append(", srcFilePath=");  
  246.         builder.append(srcFilePath);  
  247.         builder.append("]");  
  248.         return builder.toString();  
  249.     }  
  250. }  
  


回页首
  1. package org.ybygjy.web.comp;  
  2.   
  3. import java.io.BufferedInputStream;  
  4. import java.io.ByteArrayOutputStream;  
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7. import java.io.UnsupportedEncodingException;  
  8. import java.util.ArrayList;  
  9. import java.util.HashMap;  
  10. import java.util.List;  
  11. import java.util.Map;  
  12.   
  13. import javax.servlet.http.HttpServletRequest;  
  14. import javax.servlet.http.HttpServletResponse;  
  15.   
  16. import org.ybygjy.web.utils.WrapperRequest;  
  17.   
  18. /** 
  19.  * 负责对文件实体进行的操作 
  20.  * @author WangYanCheng 
  21.  * @version 2010-8-27 
  22.  */  
  23. public class FileMgrComp {  
  24.   
  25.     /** serialNumber */  
  26.     private static final long serialVersionUID = 5563862601527965192L;  
  27.     /** boundaryStr */  
  28.     private String boundaryStr;  
  29.     /** ifcArray */  
  30.     private List<FileItem> ifcArray;  
  31.   
  32.     /** 
  33.      * Constructor 
  34.      */  
  35.     public FileMgrComp() {  
  36.         ifcArray = new ArrayList<FileItem>();  
  37.     }  
  38.   
  39.     /** 
  40.      * doService 
  41.      * @param wrRequest wrRequest 
  42.      * @param response response 
  43.      * @return rtnList rtnList/null 
  44.      * @throws IOException IOException 
  45.      */  
  46.     public List<FileItem> doAnalyse(WrapperRequest wrRequest, HttpServletResponse response) throws IOException {  
  47. doInnerTest(wrRequest.getRequest());  
  48.         List<FileItem> fileArr = null;  
  49.         if (wrRequest.isBinaryData()) {  
  50.             this.boundaryStr = wrRequest.getBoundary();  
  51.             if (null != boundaryStr) {  
  52.                 fileArr = doAnalyseBinaryData(wrRequest);  
  53.             }  
  54.         }  
  55.         return fileArr;  
  56.     }  
  57.   
  58.     /** 
  59.      * 分析存储二进制数据 
  60.      * @param wrRequest wrRequest 
  61.      * @return fileItemArr fileItemArr 
  62.      */  
  63.     private List<FileItem> doAnalyseBinaryData(WrapperRequest wrRequest) {  
  64.         BufferedInputStream bins = null;  
  65.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  66.         try {  
  67.             bins = new BufferedInputStream(wrRequest.getRequest().getInputStream());  
  68.             int tmpI = -1;  
  69.             int tmpL = -1;  
  70.             while ((tmpI = bins.read()) != -1) {  
  71.                 if (tmpI == 13) {  
  72.                     tmpL = (bins.read());  
  73.                     if (tmpL == 10) {  
  74.                         if (baos.size() == 0) {  
  75.                             continue;  
  76.                         }  
  77.                         FileItem fi = analyseFileInput(baos, bins);  
  78.                         if (fi != null) {  
  79.                             ifcArray.add(fi);  
  80.                         }  
  81.                         baos.reset();  
  82.                         continue;  
  83.                     }  
  84.                     baos.write(tmpI);  
  85.                     baos.write(tmpL);  
  86.                 }  
  87.                 baos.write(tmpI);  
  88.             }  
  89.         } catch (IOException ioe) {  
  90.             ioe.printStackTrace();  
  91.         } finally {  
  92.             if (null != bins) {  
  93.                 try {  
  94.                     baos.close();  
  95.                     bins.close();  
  96.                 } catch (IOException e) {  
  97.                     e.printStackTrace();  
  98.                 }  
  99.             }  
  100.         }  
  101.         return this.getIfcArray();  
  102.     }  
  103.   
  104.     /** 
  105.      * 解析验证上传内容是否文件类型 
  106.      * @param os outStream 
  107.      * @param ins insStream 
  108.      * @return ifcInst ifcInst/null 
  109.      */  
  110.     private FileItem analyseFileInput(ByteArrayOutputStream os, InputStream ins) {  
  111.         String tmpStr = null;  
  112.         try {  
  113.             tmpStr = os.toString("UTF-8");  
  114.         } catch (UnsupportedEncodingException e1) {  
  115.             e1.printStackTrace();  
  116.         }  
  117.         FileItem ifcIns = null;  
  118.         if (tmpStr.indexOf("filename") != -1) {  
  119.             String[] tmpStrArr = tmpStr.split(";");  
  120.             if (tmpStrArr.length > 2) {  
  121.                 // 取MIME文件类型  
  122.                 ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  123.                 try {  
  124.                     doRead(ins, baos);  
  125.                     tmpStr = baos.toString();  
  126.                     if (tmpStr.startsWith("Content-Type:")) {  
  127.                         ifcIns = new FileItem(tmpStrArr[1].trim(), tmpStrArr[2].trim(),  
  128.                             tmpStr.split(":")[1].trim(), this.boundaryStr);  
  129.                         if (ifcIns.getSrcFileFullName() != null) {  
  130.                             ifcIns.doStoreFile(ins);  
  131.                         }  
  132.                     }  
  133.                 } catch (IOException e) {  
  134.                     e.printStackTrace();  
  135.                 } finally {  
  136.                     try {  
  137.                         baos.close();  
  138.                     } catch (IOException ioe) {  
  139.                         ioe.printStackTrace();  
  140.                     }  
  141.                 }  
  142.             }  
  143.         }  
  144.         return ifcIns;  
  145.     }  
  146.   
  147.     /** 
  148.      * doRead 
  149.      * @param ins ins 
  150.      * @param baos baos 
  151.      * @throws IOException IOException 
  152.      */  
  153.     private void doRead(InputStream ins, ByteArrayOutputStream baos) throws IOException {  
  154.         int tmpI = -1;  
  155.         while ((tmpI = ins.read()) != -1) {  
  156.             if (tmpI == 13) {  
  157.                 tmpI = ins.read();  
  158.                 if (tmpI == 10) {  
  159.                     break;  
  160.                 } else {  
  161.                     baos.write(13);  
  162.                     baos.write(tmpI);  
  163.                     continue;  
  164.                 }  
  165.             }  
  166.             baos.write(tmpI);  
  167.         }  
  168.     }  
  169.   
  170.     /** 
  171.      * getIfcArray 
  172.      * @return the ifcArray 
  173.      */  
  174.     public List<FileItem> getIfcArray() {  
  175.         return ifcArray;  
  176.     }  
  177.   
  178.     /** 
  179.      * innerTest 
  180.      * @param request request 
  181.      */  
  182.     private void doInnerTest(HttpServletRequest request) {  
  183.         Map<String, Object> testInfo = new HashMap<String, Object>();  
  184.         testInfo.put("AuthType", request.getAuthType());  
  185.         testInfo.put("CharacterEncoding", request.getCharacterEncoding());  
  186.         testInfo.put("ContentLength", request.getContentLength());  
  187.         testInfo.put("ContentType", request.getContentType());  
  188.         testInfo.put("ContextPath", request.getContextPath());  
  189.         testInfo.put("HeaderNames", request.getHeaderNames());  
  190.         testInfo.put("LocalAddr", request.getLocalAddr());  
  191.         testInfo.put("LocalName", request.getLocalName());  
  192.         testInfo.put("PathInfo", request.getPathInfo());  
  193.         testInfo.put("RequestedSessionId", request.getRequestedSessionId());  
  194.         testInfo.put("UserPrincipal", request.getUserPrincipal());  
  195.         org.ybygjy.test.TestUtils.doPrint(testInfo);  
  196.     }  
  197. }  
 

(三)资源

示例代码下载
下载示例代码
资料
搜集文件上传原理
表单规范
1、http://www.ietf.org:80/rfc/rfc1867.txt
2、http://www.ietf.org:80/rfc/rfc2045.txt
3、http://www.iana.org:80/assignments/character-sets
4、http://www.htmlhelp.com/reference/html40/forms/form.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值