Servlet文件接收
Posted efengsoft
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Servlet文件接收相关的知识,希望对你有一定的参考价值。
个人编写的小demo,拿走直接可以用,以下是EfengPayload.java的源文件,用法在下面写
1 import java.awt.image.BufferedImage; 2 import java.io.BufferedInputStream; 3 import java.io.ByteArrayInputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.util.HashMap; 7 import java.util.Map; 8 import javax.imageio.ImageIO; 9 import javax.servlet.ServletException; 10 import javax.servlet.http.HttpServletRequest; 11 12 public class EfengPayload { 13 private byte[] reqdata; 14 private byte[] boundary; 15 Map<String, String> payloadinfo; 16 17 EfengPayload(HttpServletRequest req) throws ServletException, IOException { 18 this.initInputData(req); 19 } 20 21 private void initInputData(HttpServletRequest req) throws ServletException, 22 IOException {// 初始化payload 23 boundary = req.getHeader("Content-Type").split("boundary=")[1] 24 .getBytes();// 获取payload的随机分割线 25 int ra; 26 InputStream in = req.getInputStream();// 获取输入流 27 BufferedInputStream br = new BufferedInputStream(in);// 缓冲流接收输入流 28 29 int byteslen = req.getContentLength();// 获取输入流长度 30 reqdata = new byte[byteslen];// 新建保存payload所有数据数组 31 for (int i = 0; (ra = br.read()) != -1; i++) { 32 reqdata[i] = (byte) ra;// 从缓冲流读取所有的数据赋值给reqdata,之后都是对这个数组进行操作 33 } 34 br.close(); 35 in.close(); 36 37 payloadinfo = new HashMap<String, String>();// 新建map,格式 38 // name->[0,1,2];0:代表内容起始位1:代表下一个内容的分割线起始位,2:当前内容起始位 39 int a[] = new int[256];// 存放每个分割线所处位置的标记数组 40 int aindex = 0;// 上面a数组的配套下标 41 for (int i = 0; i < reqdata.length; i++) {// 从头到尾遍历输入流数据 42 if (reqdata[i] == boundary[0]) { 43 for (int j = 1; j < boundary.length; j++) { 44 if (reqdata[i + j] != boundary[j]) 45 break; 46 if (j == boundary.length - 1) {// 如果有一段与boundary(随机字母分割线)匹配则将当前位置记录 47 a[aindex++] = i;// 记录当前a数组位置 48 } 49 50 } 51 } 52 } 53 byte[] namebyte = " name="".getBytes();// name特征byte数组 例如name="xxxxx 54 boolean finded = false;// 分辨当前数据块是否找到 55 for (int j = 0; j < aindex - 1; j++) { 56 int xb = a[j];// 获取当前数据块的起始坐标数值 57 finded = false;// 每次进入前设置没找到 58 for (int k = xb; k < a[j + 1]; k++) { 59 if (reqdata[k] == namebyte[0]) { 60 61 for (int m = 1; m < namebyte.length; m++) { 62 63 if (reqdata[k + m] != namebyte[m]) 64 break; 65 if (m == namebyte.length - 1) {// 从namebyte的第一位到最后一位都匹配成功 66 finded = true;// 找到name 67 StringBuilder mapname = new StringBuilder(); 68 int n; 69 for (n = k + m + 1;; n++) {// 请求数据从name=“位置+1处开始收集name信息 70 if (reqdata[n] == (byte) ‘"‘)// 如果”意味着name收集结束,通常格式name=“xxx” 71 break; 72 mapname.append((char) reqdata[n]);// 填入当前位 73 } 74 for (int o = n + 1; o < a[j + 1]; o++) {// 继续往下一直搜索直到搜索到数据开头处 75 if (reqdata[o] == (byte) ‘ ‘ 76 && reqdata[o - 2] == (byte) ‘ ‘) {// 特征符合 77 payloadinfo.put(mapname.toString(), o + 1 78 + "," + a[j + 1] + "," + a[j]);// map中记录当前数据块的name 79 // ,内容起始位,下一个内容的分割线起始位,当前内容起始位 80 break; 81 } 82 83 } 84 85 } 86 if (finded)// 如果找到跳出当前循环 87 break; 88 } 89 } 90 if (finded)// 如果找到跳出当前循环 91 break; 92 } 93 } 94 } 95 96 public byte[] getPayloadByteValue(String name) { 97 String[] indexs = payloadinfo.get(name).split(",");// 私有map中记录的各块的基本信息 98 int bstart = Integer.parseInt(indexs[0]), bend = Integer 99 .parseInt(indexs[1]);// 数据起始位与下一数据头(头分割线)的起始位 100 101 for (int j = bend;; j--) { 102 if (reqdata[j] == 10 && reqdata[j - 1] == 13) { 103 bend = j - 1;// 找到特征,确定结束位置 104 break; 105 } 106 } 107 byte[] retbyt = new byte[bend - bstart];// 确定返回数组大小 108 for (int i = bstart; i < bend; i++) {// 取出区间数据 109 retbyt[i - bstart] = reqdata[i]; 110 } 111 112 return retbyt; 113 114 } 115 public String getPayloadValue(String name){ 116 StringBuilder retstr=new StringBuilder(); 117 byte[] bytename=getPayloadByteValue(name); 118 for(byte a : bytename) 119 retstr.append((char)a); 120 return retstr.toString(); 121 } 122 public String getPayloadOthers(String name, String type) { 123 if ("Content-Type".equals(type)) 124 type = " " + type + ": "; 125 else 126 type = (" " + type + "=""); 127 byte[] typebyte = type.getBytes(); 128 int end = Integer.parseInt(payloadinfo.get(name).split(",")[0]);// 0代表数据起始位置 129 int start = Integer.parseInt(payloadinfo.get(name).split(",")[2]);// 2代表数据前面标记的起始位置 130 for (int i = start; i < end; i++) { 131 if (reqdata[i] == typebyte[0]) { 132 for (int j = 1; j < typebyte.length; j++) { 133 if (reqdata[i + j] != typebyte[j]) 134 break; 135 if (j == typebyte.length - 1) { 136 String rtsstr = ""; 137 for (int k = i + j + 1;; k++) { 138 if ((char) reqdata[k] == ‘;‘ 139 || (char) reqdata[k] == ‘"‘ 140 || (char) reqdata[k] == ‘ ‘ 141 || (char) reqdata[k] == (char)13)//回车 142 return rtsstr; 143 rtsstr += (char) reqdata[k]; 144 } 145 } 146 } 147 } 148 } 149 return null; 150 } 151 152 public BufferedImage getImage(String name) throws IOException { 153 154 byte nameByte[] = this.getPayloadByteValue(name); 155 ByteArrayInputStream imageinput = new ByteArrayInputStream(nameByte); 156 BufferedImage buf = ImageIO.read(imageinput); 157 return buf; 158 } 159 }
用法1:接收图片并向servlet的响应输出流中输出图片
前端代码
1 <form method="post" target="_top" action="MyFileTest" enctype="multipart/form-data"> 2 选择一个文件: 3 <input type="file" name="file" /><br/> 5 <input type="submit" value="上传" /> 6 </form>
后端代码
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { EfengPayload efeng=new EfengPayload(req); ImageIO.write( efeng.getImage("file"), //参数file是前端传来的name值 efeng.getPayloadOthers("file", "Content-Type") .split("/")[1],//根据name值(file)查询文件类型 resp.getOutputStream() ); }
用法2:根据name获取指定的value值
前端添加input组件
1 <form method="post" target="_top" action="MyFileTest" enctype="multipart/form-data"> 2 选择一个文件: 3 <input type="file" name="file" /> 4 <br/><input type="text" name="username" /><br/>//前端增加username输入框 5 <input type="submit" value="上传" /> 6 </form>
后端添加对应获取语句,如下红色部分
1 protected void doGet(HttpServletRequest req, HttpServletResponse resp) 2 throws ServletException, IOException { 3 EfengPayload efeng=new EfengPayload(req); 4 ImageIO.write( 5 efeng.getImage("file"), 6 efeng.getPayloadOthers("file", "Content-Type") 7 .split("/")[1], 8 resp.getOutputStream() 9 ); 10 System.out.println(efeng.getPayloadValue("username"));//获取前端name为username的组件值 11 12 }
efeng.getPayloadOthers("对应name名", "想获取的项"),例如想获得下面name为file的filename就可以执行:
String str=efeng.getPayloadOthers("file", "filename");
想获得下面的数据部分可以执行
byte[] bytedata=efeng.getPayloadByteValue("file");