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");

技术图片

 

 

以上是关于Servlet文件接收的主要内容,如果未能解决你的问题,请参考以下文章

ajax上传文件后,后台java如何接收(求后台接收的完整代码)

jsp初识servlet转发转发与重定向的比较

Servlet文件接收

从广播接收器更改片段

无法在片段内查看接收短信

从广播接收器更新片段中的列表视图