大橙子网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
创新互联www.cdcxhl.cn八线动态BGP香港云服务器提供商,新人活动买多久送多久,划算不套路!
为陇南等地区用户提供了全套网页设计制作服务,及陇南网站建设行业解决方案。主营业务为成都网站设计、做网站、陇南网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!我想做过web开发的程序员大部分都做过文件上传的功能,大多数时候我们都是借助于commons-fileupload这样的jar包实现的。下面我试着通过读取Socket的输入流来实现一个文件上传的功能。
在做文件上传之前我们需要先了解一下HTTP POST的附件上传协议。HTTP附件上传协议是RFC1876协议,RFC1876协议是在HTTP协议的基础上为INPUT标签增加了file属性,同时限定了Form的method必须为POST
,ENCTYPE
必须为multipart/form-data
。RFC1867协议对HTTP头作了适当地变更,content-type头由以前的:content-type:application/x-www-form-urlencoded变为content-type:multipart/form-data;+空格+boundary=字符串
。RFC1867增加了文件上传得功能,而上传文件内容自然也会被加入到HTTP的实体中。现在因为既有HTTP一般的参数实体,又有上传文件的实体,所以用boundary把每种实体进行了分割。具体的看下图:
接下来就开始我们的代码部分吧。
我在前面的文章中写过创建一个自己的Web服务器,现在我们的重点要放在对socket的输入流的解析中。具体代码如下:
public void parseRequest() { LineNumberReader br = new LineNumberReader(new InputStreamReader(inputStream)); StringBuffer sb = new StringBuffer(); String str = null; try { //读取请求行 String requestLine = br.readLine(); if (!StringUtils.isEmpty(requestLine)) { sb.append(requestLine); String[] reqs = requestLine.split(" "); if (reqs != null && reqs.length > 0) { if ("GET".equals(reqs[0])) { method = "GET"; } else { method = "POST"; } } } //读取请求头 while ((str = br.readLine()) != null) { if ("".equals(str)) { break; } if (!StringUtils.isEmpty(str)) { if (str.indexOf(":") > 0) { String[] strs = str.split(":"); headers.put(strs[0].toLowerCase(), strs[1].trim()); } } sb.append(str).append("\n"); } //POST请求,Content-type为 multipart/form-data String contentType = null; if ("POST".equals(method) && ((contentType = headers.get("content-type")) != null && headers.get("content-type").startsWith("multipart/form-data"))) { //文件上传的分割位 这里只处理单个文件的上传 String boundary = contentType.substring(contentType.indexOf("boundary") + "boundary=".length()); //解析消息体 while ((str = br.readLine()) != null) { //解析结束的标记 do { //读取boundary中的内容 //读取Content-Disposition str = br.readLine(); //说明是文件上传 if (str.indexOf("Content-Disposition:") >= 0 && str.indexOf("filename") > 0) { str = str.substring("Content-Disposition:".length()); String[] strs = str.split(";"); String fileName = strs[strs.length - 1].replace("\"", "").split("=")[1]; System.out.println("fileName = " + fileName); //这一行是Content-Type br.readLine(); //这一行是换行 br.readLine(); //正式去读文件的内容 BufferedWriter bw = null; try { bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("G:\\LearnVideo\\fileLoad" + File.separator + fileName), "UTF-8")); while (true) { str = br.readLine(); if (str.startsWith("--" + boundary)) { break; } bw.write(str); bw.newLine(); } bw.flush(); } catch (Exception e) { } finally { if (bw != null) { bw.close(); } } } if (str.indexOf("Content-Disposition:") >= 0) { str = str.substring("Content-Disposition:".length()); String[] strs = str.split(";"); String name = strs[strs.length - 1].replace("\"", "").split("=")[1]; br.readLine(); StringBuilder stringBuilder = new StringBuilder(); while (true) { str = br.readLine(); if (str.startsWith("--" + boundary)) { break; } stringBuilder.append(str); } parameters.put(name, stringBuilder.toString()); } } while (("--" + boundary).equals(str)); //解析结束 if (str.equals("--" + boundary + "--")) { break; } } } //System.out.println(sb.toString()); //获取URI uri = StringUtils.parserUri(sb.toString(), " "); int flag = -1; //说明有参数 if ((flag = uri.indexOf('?')) >= 0) { String oldUri = uri; uri = uri.substring(0,flag); String parameterPath = oldUri.substring(flag+1); String[] parameter = parameterPath.split("&"); if (parameter != null && parameter.length > 0) { for (int i = 0; i < parameter.length; i++) { String str1 = parameter[i]; if((flag = str1.indexOf('=')) >= 0){ String key = str1.substring(0,flag); String value = str1.substring(flag+1); parameters.put(key,value); }else{ parameters.put(str,null); } } } } } catch (IOException e) { e.printStackTrace(); } }