文件的上传和下载以及如何防止网站被入侵(web开发中很有用的知识)

来源:互联网 发布:炫舞辅助源码 编辑:程序博客网 时间:2024/06/04 19:43
文件上传:允许客户将本地文件,上传到服务器端 
应用:上传照片、上传新闻图片、上传附件 


一、文件上传编程
1、在用户页面中添加上传输入项 (客户端页面操作)
<input type="file" />
注意事项:
1) 必须为文件上传input 提供name属性,否则文件上传内容不会被表单提交 
2) 表单的提交是post (get提交数据在url地址上显示,有长度限制) 
3) 设置enctype=multipart 使得文件上传编码 ----- MIME编码格式


2、在服务器端编写文件上传程序
通过request.getInputStream分析文件上传原理 


常用文件上传API : 
1) JSP独立开发年代 jsp-smartupload ---- JSP Model1 
jspSmartUpload是一个可免费使用的全功能的文件上传下载组件,适于嵌入执行上传下载操作的JSP文件中。
2) JSP+Servlet 开发web应用 Apache commons-fileupload ---- JSP Model2
FileUpload 是 Apache commons下面的一个子项目,用来实现Java环境下面的文件上传功能,与常见的SmartUpload齐名。
3) Servlet3.0规范中提供对文件上传的支持 


Apache commons-fileupload 使用
1) 去 http://commons.apache.org/fileupload/ 下载fileupload jar包 
同时下载 commons-fileupload 和  commons-io 两个包  -------- fileupload依赖io包 


2) 将jar包导入 web 工程WEB-INF/lib下 
3) 编程实现
步骤一:获得DiskFileItemFactory 文件项工厂
步骤二:通过工厂 获得文件上传请求核心解析类 ServletFileUpload 
步骤三:使用ServletFileUpload对request进行解析  ---- 获得很多个FileItem
步骤四:对每个FileItem进行操作 判断FileItem是不是普通字段 isFormField 
代表普通字段FileItem 
getFieldName();  ---- 获得表单项name属性
getString(); ----- 获得表单项value


代表文件上传FileItem
getInputStream() --- 获得文件内容输入流
getName() ------ 获得上传文件名称


============================================================================================================================
问题:早期IE6 浏览器提交,上传文件时,请求中存放是客户端完整路径 ----- 在服务器端保存文件时,需要切掉客户端路径,只保留文件名
int index = filename.lastIndexOf("\\");
if (index != -1) {
filename = filename.substring(index + 1);// 获得真实文件名
}
============================================================================================================================
二、commons-fileupload 核心API 分析
1、DiskFileItemFactory 磁盘文件项工厂类 
public DiskFileItemFactory(int sizeThreshold, java.io.File repository)  构造工厂时,指定内存缓冲区大小和临时文件存放位置


public void setSizeThreshold(int sizeThreshold) 设置内存缓冲区大小,默认10K


public void setRepository(java.io.File repository)设置临时文件存放位置,默认System.getProperty("java.io.tmpdir"). 


内存缓冲区: 上传文件时,上传文件的内容优先保存在内存缓冲区中,当上传文件大小超过缓冲区大小,就会在服务器端产生临时文件 
临时文件存放位置: 保存超过了内存缓冲区大小上传文件而产生临时文件 
* 产生临时文件可以通过 FileItem的delete方法删除 


2、ServletFileUpload 文件上传核心类 
static boolean  isMultipartContent(javax.servlet.http.HttpServletRequest request)  判断request的编码方式是否为multipart/form-data


java.util.List parseRequest(javax.servlet.http.HttpServletRequest request) 解析request,将请求体每个部分封装FileItem对象,返回List<FileItem>


void setFileSizeMax(long fileSizeMax) 设置单个文件上传大小  和 void  setSizeMax(long sizeMax) 设置总文件上传大小 


void setHeaderEncoding(java.lang.String encoding)  设置编码集 解决上传文件名乱码 ***** 


void setProgressListener(ProgressListener pListener) 设置文件上传监听器 (用来监控文件上传进度)
* 上传时间、剩余大小、速度、剩余时间 


3、FileItem 表示文件上传表单中 每个数据部分 
boolean isFormField()  判断该数据项是否为文件上传项,true 不是文件上传 false 是文件上传
if(fileItem.isFormField()){
   // 不是上传项
   java.lang.String getFieldName()  获得普通表单项name属性
   java.lang.String getString() / java.lang.String getString(java.lang.String encoding) 获得普通表单项value属性 传入编码集用来解决输入value乱码 
}else{
   // 是上传项
   java.lang.String getName() 获得上传文件名 (注意IE6存在路径)
   java.io.InputStream getInputStream() 获得上传文件内容输入流
   // 上传文件
   void delete()  删除临时文件(删除时,必须要管理输入输出流)
}


注意事项:因为文件上传表单采用编码方式multipart/form-data 与传统url编码不同,所有getParameter 方法不能使用 setCharacterEncoding 无法解决输入项乱码问题 


三 JavaScript的多文件上传表单 


四 上传文件注意问题 
1、上传文件后,在服务器端保存位置
第一类存放位置:直接存放WebRoot目录下 和 除WEB-INF META-INF的其它子目录下  例如: WebRoot/upload 
* 客户端可以直接在浏览器上通过url访问位置(资料无需通过权限控制,而可以直接访问) ---- 对上传资源安全性要求不高、或者资源需要用户直接可见
* 例如:购物商城商品图片


第二类存放位置:放入WEB-INF及其子目录 或者 不受tomcat服务器管理目录 例如: WebRoot/WEB-INF/upload 、c:\ 、d:\abc
* 客户端无法通过URL直接访问,必须由服务器内部程序才能读取 (安全性较高,可以很容易添加权限控制)
* 例如:会员制在线视频 


2、上传文件在同一个目录重名问题 
如果文件重名,后上传文件就会覆盖先上传文件 


文件名 UUID 
filename = UUID.randomUUID().toString() + "_" + filename;


3、为了防止同一个目录下方上传文件数量过多 ---- 必须采用目录分离算法 
1) 按照上传时间进行目录分离 (周、月 )
2) 按照上传用户进行目录分离 ----- 为每个用户建立单独目录 
3) 按照固定数量进行目录分离 ------ 假设每个目录只能存放3000个文件 ,每当一个目录存满3000个文件后,创建一个新的目录
4) 按照唯一文件名的hashcode 进行目录分离  
public static String generateRandomDir(String uuidFileName) {
// 获得唯一文件名的hashcode
int hashcode = uuidFileName.hashCode();
// 获得一级目录
int d1 = hashcode & 0xf;
// 获得二级目录
int d2 = (hashcode >>> 4) & 0xf;


return "/" + d2 + "/" + d1;// 共有256目录
}


4、乱码问题 
普通编写项 value属性乱码 ------------- fileItem.getString(编码集);
上传文件项 文件名乱码 --------- fileupload.setHeaderEncoding(编码集);


=========================================================================================================================
五、上传文件的进度监控 
ServletFileUpload 类 提供 public void setProgressListener(ProgressListener pListener) 
* 为文件上传程序绑定一个监听器对象,通过监听器可以监听文件上传全过程 
* 和AJAX技术结合,编写文件上传进度条 


设置监听器,文件上传程序会自动执行 监听器中 update方法 public void update(long pBytesRead, long pContentLength, int pItems)


在方法中可以获得 文件总大小、已经上传大小和 上传第几个元素 


能否根据上面三个参数计算:剩余大小、传输速度、已用时间、剩余时间
1) 已用时间 = 当前时间 - 开始时间
2) 速度 = 已经上传大小/已用时间
3) 剩余大小 = 总大小- 已经上传大小
4) 剩余时间 = 剩余大小/速度 


六、文件下载 
将服务器端文件下载到客户端  


常见文件下载有两种编写方式 
1、超链接直接指向下载资源 
如果文件格式浏览器识别,将直接打开文件,显示在浏览器上, 如果文件格式浏览器不识别,将弹出下载窗口 
对于浏览器识别格式的文件,通过另存为进行下载 


客户端访问服务器静态资源文件时,静态资源文件是通过 缺省Servlet返回的,在tomcat配置文件conf/web.xml 找到 --- org.apache.catalina.servlets.DefaultServlet


2、编写服务器程序,读取服务器端文件,完成下载 
必须设置两个头信息 ,来自MIME协议  Content-Type  Content-Disposition 


response.setContentType(getServletContext().getMimeType(filename));
response.setHeader("Content-Disposition", "attachment;filename=" + filename); // 以附件形式打开,不管格式浏览器是否识别 


七、下载案例:指定一个磁盘目录,通过树形结构遍历,遍历磁盘目录下及其子目录中文体 ,提供下载 
* 遍历一个树形目录结构中所有文件 


1、广度非递归 遍历目录中所有文件 


2、使用get方式提交中文时 
<a href="/day21/downloadList?path=D:\TTPmusic\何晟铭\何晟铭 - 爱的供养.mp3">何晟铭 - 爱的供养.mp3</a><br/> 
问题:IE6 提交后,服务器经过get乱码处理获得 乱码 
原因:IE6对中文直接进行 get提交时,进行URL编码 ---- 编码发生问题 
解决:手动对get提交中文进行编码  ----- URLEncoder 


3、如果下载文件是中文名,设置 response.setHeader("Content-Disposition", "attachment;filename=" + filename); 出现附件名乱码
不同浏览器处理下载附件名乱码 处理方式不同 ,例如 IE使用URL编码 、FF使用 BASE64编码 


通过USER-AGENT 请求头信息字段,判断来访者浏览器类型 
** 问题:火狐浏览器 在使用MimeUtility 进行Base64编码 时存在问题 ,如果字符串中没有中文,无法进行编码 
解决:采用手动BASE64 编码 
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 知道扣扣号怎样盗取他的密码怎么办 喜欢养猫又怕猫破坏家里怎么办 约她她每次都找借口怎么办? 遇到总是找借口不还钱的人怎么办 装修好了业主找借口不给钱怎么办 荒野行动手机换了帐号登不上怎么办 换新手机后微信头像都没有了怎么办 苹果系统维护换不了微信头像怎么办 系统通知栏不显示qq图标怎么办 快递号码写错了而且发货了怎么办 包裹遗忘在郑州东站安检口了怎么办 锁书包的锁头钥匙全掉了怎么办 平板电脑恢复出厂设置变英语怎么办 给国外银行汇款账号写错账号怎么办 顺丰快递暴力运输产品坏了怎么办 亚航订机票名字少写一个字母怎么办 如果淘宝付款七天内不发货怎么办 浪琴手表调了一下日期不走了怎么办 收件人号码写错快递柜已签收怎么办 医院名字写错了怎么办保险报销 电脑在使用中出现了英文字慕怎么办 下雨天了怎么办我好想你是什么歌 安卓手机不支持微信运动怎么办 装系统时无法跳过密匙怎么办 在msdn里下的系统没有网怎么办 w7电脑更新后系统没法激活怎么办 手机使用加速器后网速变卡怎么办 奥特曼ol分解了迪迦石像怎么办 左右棋牌游戏兑换总说系统护怎么办 四季海棠扦插以后黄叶卷叶怎么办 竹节海棠浇水多了叶子蔫了怎么办 社保停缴了里面的钱怎么办 王者荣耀英雄释放技能有延迟怎么办 买的桑拿木板颜色太深了怎么办 万一填写了奔跑吧诈骗信息该怎么办 深圳限行时段堵在路上怎么办 开车堵在路上到了限行时间怎么办 兄妹之间都不想照顾母亲我该怎么办 小孩扁体发炎睡觉呼吸声沉重怎么办 客所思pk3老驱动有杂音怎么办 手机打不开解压包密码怎么办