我想做过网络开发的程序员大部分都做过文件上传的功能,大多数时候我们都是借助于commons-fileupload这样的jar包实现的。下面我试着通过读取套接字的输入流来实现一个文件上传的功能。
在做文件上传之前我们需要先了解一下HTTP POST的附件上传协议.北京附件上传协议是RFC1876协议,RFC1876协议是在HTTP协议的基础上为输入标签增加了文件属性,同时限定了形式的方法必须为<代码> 代码>,<代码> ENCTYPE> 代码必须为<代码>多部分/格式> 代码.RFC1867协议对HTTP头作了适当地变更,内容类型头由以前的:内容类型:应用程序/x-www-form-urlencoded变为<代码>内容类型:多部分/格式;+空格+边界=字符串代码> .RFC1867增加了文件上传得功能,而上传文件内容自然也会被加入到HTTP的实体中。现在因为既有HTTP一般的参数实体,又有上传文件的实体,所以用边界把每种实体进行了分割。具体的看下图:
接下来就开始我们的代码部分吧。
我在前面的文章中写过创建一个自己的Web服务器,现在我们的重点要放在对套接字的输入流的解析中。具体代码如下:
公共空间parseRequest () { LineNumberReader br=new LineNumberReader(新InputStreamReader (inputStream)); StringBuffer某人=new StringBuffer (); 字符串str=零; 尝试{//读取请求行 字符串requestLine=br.readLine (); 如果(! StringUtils.isEmpty (requestLine)) { sb.append (requestLine); String[]请求=requestLine。分割(" "); 如果请求!=零,,请求。长度比;0){ 如果“获得”.equals(请求[0])){ 方法=盎竦谩? 其他}{ 方法=癙OST”; } } }//读取请求头 在((str=br.readLine ()) !=null) { 如果“.equals (str)) { 打破; } 如果(! StringUtils.isEmpty (str)) { 如果(str.indexOf祝辞(“:”);0){ String [] str=str.split (“:”); headers.put (str [0] .toLowerCase (), str [1] .trim ()); } } sb.append (str) .append (“\ n”); }//后请求,内容类型为多部分/格式 字符串contentType=零; 如果(“POST”.equals(方法),,((contentType=headers.get(“内容类型”))!=零 ,,headers.get .startsWith(“内容类型”)(“多部分/格式”))){//文件上传的分割位这里只处理单个文件的上传 字符串边界=contentType.substring (contentType.indexOf(“边界”)+ “边界=" . length ());//解析消息体 在((str=br.readLine ()) !=null) {//解析结束的标记 {做//读中取边界的内容//读取附加项 str=br.readLine ();//说明是文件上传 如果(str.indexOf(“附加项:“)在=0,,str.indexOf祝辞(“文件名”);0){ str=str.substring(“附加项:“. length ()); String [] str=str.split (“;”); 字符串文件名=str (str。长度- 1)。替换(“\“”、“”).split ("=") [1]; system . out。println(“文件名=" +文件名);//这一行是内容类型 br.readLine ();//这一行是换行 br.readLine ();//正式去读文件的内容 BufferedWriter bw=零; 尝试{ bw=new BufferedWriter(新OutputStreamWriter(新 FileOutputStream (“G: \ \ LearnVideo \ \ fileLoad”+ 文件。分离器+文件名)" utf - 8 ")); 而(真){ str=br.readLine (); 如果(str.startsWith(”——“+边界)){ 打破; } bw.write (str); bw.newLine (); } bw.flush (); }捕捉(异常e) { 最后}{ 如果(bw !=null) { bw.close (); } } } 如果(str.indexOf(“附加项:“)在=0){ str=str.substring(“附加项:“. length ()); String [] str=str.split (“;”); 字符串名称=str (str。长度- 1)。替换(“\“”、“”).split ("=") [1]; br.readLine (); StringBuilder StringBuilder=new StringBuilder (); 而(真){ str=br.readLine (); 如果(str.startsWith(”——“+边界)){ 打破; } stringBuilder.append (str); } 参数。把(名称、stringBuilder.toString ()); } },((”——“+边界).equals (str));//解析结束 如果(str.equals(边界”——“+ +”——“)){ 打破; } } }//System.out.println (sb.toString ());//获取URI uri=StringUtils.parserUri (sb.toString () " "); int标志=1;//说明有参数 如果((国旗=uri.indexOf(' & # 63; '))在=0){ 字符串oldUri=uri; uri=uri.substring(0,国旗); 字符串parameterPath=oldUri.substring(国旗+ 1); String[]参数=parameterPath.split (", "); 如果(参数!=零,,参数。长度比;0){ for (int i=0;我& lt;parameter.length;我+ +){ 字符串str1=参数[我]; 如果((国旗=str1.indexOf('='))在=0){ 字符串键=str1.substring(0,国旗); 字符串值=https://www.yisu.com/zixun/str1.substring(国旗+ 1); parameters.put(关键字,值); 其他}{ parameters.put (str, null); } } } } }捕捉(IOException e) { e.printStackTrace (); } }Java中用套接字实现HTTP文件上传实例