我想做过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();
}
}
我们启动自己创建的Web服务器,然后在浏览器中输入:http://localhost:8004/static/uploadPage.html,页面如下:
选择我们要上次的文件,然后点击上传按钮,我们会发现我们的功能已经被上传到G:\LearnVideo\fileLoad这个目录下了。示例如下:
完整的代码请从这里下载:FullStackTraining_jb51.rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# socket实现文件上传
# java
# socket实现http
# socket
# http
# 文件上传
# Java 基于TCP Socket 实现文件上传
# Socket+JDBC+IO实现Java文件上传下载器DEMO详解
# Java Socket+mysql实现简易文件上传器的代码
# JavaWeb实现文件上传下载功能实例解析
# JAVA中使用FTPClient实现文件上传下载实例代码
# java实现FTP文件上传与文件下载
# JavaWeb实现文件上传下载功能实例详解
# java web图片上传和文件上传实例
# Java实现文件上传至服务器的方法
# java使用Socket实现文件上传功能
# 上传
# 做过
# 这一行
# 自己的
# 上传文件
# 都是
# 增加了
# 我想
# 是在
# 我在
# 也会
# 又有
# 下了
# 作了
# 在对
# 定了
# 试着
# 来实现
# 这里下载
相关文章:
清单制作人网站有哪些,近日“兴风作浪的姑奶奶”引起很多人的关注这是什么事情?
定制建站方案优化指南:企业官网开发与建站费用解析
Python如何创建带属性的XML节点
焦点电影公司作品,电影焦点结局是什么?
建站之星ASP如何实现CMS高效搭建与安全管理?
香港服务器选型指南:免备案配置与高效建站方案解析
实现点击下箭头变上箭头来回切换的两种方法【推荐】
宝塔建站助手安装配置与建站模板使用全流程解析
广州网站建站公司选择指南:建站流程与SEO优化关键词解析
网站制作企业,网站的banner和导航栏是指什么?
自助网站制作软件,个人如何自助建网站?
如何快速配置高效服务器建站软件?
建站之星安装路径如何正确选择及配置?
ppt在线制作免费网站推荐,有什么下载免费的ppt模板网站?
微信小程序 五星评分(包括半颗星评分)实例代码
C++如何将C风格字符串(char*)转换为std::string?(代码示例)
如何通过商城免费建站系统源码自定义网站主题?
如何配置IIS站点权限与局域网访问?
惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?
c++如何打印函数堆栈信息_c++ backtrace函数与符号名解析【方法】
网站制作知乎推荐,想做自己的网站用什么工具比较好?
番禺网站制作公司哪家值得合作,番禺图书馆新馆开放了吗?
如何快速搭建FTP站点实现文件共享?
沈阳制作网站公司排名,沈阳装饰协会官方网站?
定制建站模板如何实现SEO优化与智能系统配置?18字教程
威客平台建站流程解析:高效搭建教程与设计优化方案
重庆网站制作公司哪家好,重庆中考招生办官方网站?
南京做网站制作公司,南京哈发网络有限公司,公司怎么样,做网页美工DIV+CSS待遇怎么样?
宝塔建站后网页无法访问如何解决?
建站主机功能解析:服务器选择与快速搭建指南
如何优化Golang Web性能_Golang HTTP服务器性能提升方法
,制作一个手机app网站要多少钱?
如何配置支付宝与微信支付功能?
php条件判断怎么写_ifelse和switchcase的使用区别【对比】
如何选购建站域名与空间?自助平台全解析
rsync同步时出现rsync: failed to set times on “xxxx”: Operation not permitted
广东专业制作网站有哪些,广东省能源集团有限公司官网?
如何在IIS7上新建站点并设置安全权限?
定制建站是什么?如何实现个性化需求?
如何快速查询网址的建站时间与历史轨迹?
大连网站设计制作招聘信息,大连投诉网站有哪些?
制作网站的过程怎么写,用凡科建站如何制作自己的网站?
c++ stringstream用法详解_c++字符串与数字转换利器
Swift中循环语句中的转移语句 break 和 continue
如何选择PHP开源工具快速搭建网站?
专业网站制作企业网站,如何制作一个企业网站,建设网站的基本步骤有哪些?
C#怎么使用委托和事件 C# delegate与event编程方法
深圳企业网站制作设计,在深圳如何网上全流程注册公司?
高配服务器限时抢购:企业级配置与回收服务一站式优惠方案
宿州网站制作公司兴策,安徽省低保查询网站?
*请认真填写需求信息,我们会在24小时内与您取得联系。