首页 > 代码库 > java web(四)文件上传与下载

java web(四)文件上传与下载

一、文件上传原理

  1、在TCP/IP中,最早出现的文件上传机制是FTP ,它是将文件由客户端发送到服务器的标准机制;但是在jsp使用过程中不能使用FTP方法上传文件,这是由jsp运行机制所决定。  

  通过为表单元素设置 method="post" enctype="multipart/form-data" 属性 ,让表单提交的数据以二进制编码的方式提交,在接受此请求的Servlet中用二进制流来获取内容,就可以取得上传文件的内容,从而实现文件的上传。

  2、表单enctype属相

    1>application/x-www-form-urlencoded

    默认编码方式,只处理表单域里的value属性值,采用这种编码方式的表单域中的值处理成URL编码方式。

    2>multipart/form-data

    这种编码方式的表单会以二进制流的方式处理表单数据,  这种编码方式会把文件域指定的文件内容也封装到请求参数中。

    3>text/plain

    这种方式主要适用于直接通过表单发送邮件的方式。

二、SmartUpload上传组件的使用

  SmartUpload组件使用简单,可以轻松的实现上传文件类型的限制,也可以轻易地取得上传文件的名称、后缀、大小。  使用该组件需要导入jar包,我用的是 jspsmartupload.jar。

 1、上传单个文件

upload.htm

<html>
  <head>
  <title>文件上传</title>
  </head>
<body>
  <form action="upload.jsp" method="post" enctype="multipart/form-data">
    请选择文件:<input type="file" name="pic">
    <input type="submit" value="http://www.mamicode.com/上传">
  </form>
</body>
</html>

upload.jsp

<%@ page contentType="text/html" pageEncoding="utf-8"%>
<%@ page import="com.jspsmart.upload.*"%>
<html>
<head>
<title>文件上传2</title>
</head>
<body>
<%
SmartUpload smart=new SmartUpload();
smart.initialize(pageContext);
smart.upload();
smart.save("upload");
%>
</body>
</html>

这里要注意在jsp页面引入导入jar包中的类文件:上面是com.jspsmart.upload.*,为什么这样写,可以用360压缩打开jar包文件如下:

技术分享

upload表示上传文件的保存文件夹,该文件夹要在跟目录手动建立。上传结果如下:

技术分享

2、混合表单

  如果要上传文件,表单必须封装,但是表单使用了enctype 封装后其他非文件类的表单控件无法通过request内置对象取得,此时必须通过SmartUpload类的getRequest()方法取得全部请求参数。

upload2.htm

<html>
<head>
<title>文件上传</title>
</head>
<body>
<form action="upload2.jsp" method="post" enctype="multipart/form-data">
姓名:<input type="text" name="uname"><br>
照片:<input type="file" name="pic"><br>
<input type="submit" value="http://www.mamicode.com/上传">
<input type="reset" value="http://www.mamicode.com/重置">
</form>
</body>
</html>

upload2.jsp

<%@ page contentType="text/html" pageEncoding="utf-8"%>
<%@ page import="com.jspsmart.upload.*"%>
<html>
<head>
<title>文件上传2</title>
</head>
<body>
<%
SmartUpload smart=new SmartUpload();    //实例化SmartUpload上传组件
smart.initialize(pageContext);          //初始化上传操作
smart.upload();                  //上传准备
String name=smart.getRequest().getParameter("uname");  //接受请求参数
smart.save("upload");              //将上传文件保存在upload文件夹中
%>
<h2>姓名:<%=name%></h2>
<h2>request=:<%=request.getParameter("uname")%></h2>
</body>
</html>

技术分享

3、为上传文件自动命名

    主要为了防止重名情况下发生覆盖文件。以下例子中文件命名采用 IP地址+时间戳+三位随机数

upload3.htm

<html>
<head>
<title>文件上传</title>
</head>
<body>
<form action="upload3.jsp" method="post" enctype="multipart/form-data">
姓名:<input type="text" name="uname"><br>
照片:<input type="file" name="pic"><br>
<input type="submit" value="http://www.mamicode.com/上传">
<input type="reset" value="http://www.mamicode.com/重置">
</form>
</body>
</html>

upload3.jsp

<%@ page contentType="text/html" pageEncoding="utf-8"%>
<%@ page import="com.jspsmart.upload.*"%>
<%@ page import="kk.upload3.IPTimeStamp"%>
<html>
<head>
<title>文件上传3</title>
</head>
<body>
<%
request.setCharacterEncoding("utf-8");
//实例化SmartUpload上传组件
SmartUpload smart=new SmartUpload();
//初始化上传操作
smart.initialize(pageContext);
//上传准备
smart.upload();
//接受请求参数
String name=smart.getRequest().getParameter("uname");

IPTimeStamp its=new IPTimeStamp(request.getRemoteAddr());
//取得文件后缀名
String ext=smart.getFiles().getFile(0).getFileExt();
//拼凑文件名称
String fileName=its.getIPTimeRand()+"."+ext;
System.out.println("文件名称及后缀==>"+fileName);
//保存文件

smart.getFiles().getFile(0).saveAs(getServletContext().getRealPath("/")
+"upload"+java.io.File.separator+fileName);

//./表示当前目录;../表示源文件所在目录的上一级目录;../../表示源文件所在目录的上上级目录,以此类推
%>

<%=getServletContext().getRealPath("/")+"upload"+java.io.File.separator+fileName %>
<h2>姓名:<%=name%></h2>

<img src="http://www.mamicode.com/upload/">
</body>
</html>

 

IPTimeStamp.java

package kk.upload3;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
public class IPTimeStamp{

private SimpleDateFormat sdf=null;
private String ip=null;

public IPTimeStamp(){

}
public IPTimeStamp(String ip){
this.ip=ip;
//System.out.println("ip="+ip);
}

//得到IP地址+时间戳+三位随机数
public String getIPTimeRand(){

StringBuffer buf=new StringBuffer();
if(this.ip!=null){
/*
* 进行拆分操作
* 在java中 \代表转义字符 \n \t 等,而 \\ 代表一个反斜杠 而.代表一个元字符
* 要表示一个.就需要用 要用\.
* 所以"\\." 在实际编译中 就代表 .
* */
String s[]=this.ip.split("\\.");
for(int i=0;i<s.length;i++){

//不够三位数字补0
buf.append(this.addZero(s[i],3));
}
}
//取得时间戳
buf.append(this.getTimeStamp());
Random r=new Random();
for(int i=0;i<3;i++){

buf.append(r.nextInt(10));
}
System.out.println("文件前缀==>"+buf.toString());
return buf.toString();
}

private String addZero(String str,int len){

StringBuffer s=new StringBuffer();
s.append(str);
while(s.length()<len){
s.insert(0,"0");
}
//System.out.println(s);
return s.toString();
}

public String getDate(){
this.sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
return this.sdf.format(new Date());
}

public String getTimeStamp(){
this.sdf=new SimpleDateFormat("yyyyMMddHHmmssSSS");
return this.sdf.format(new Date());
}

}

运行结果:

技术分享

 

问题:限制文件上传类型?

比如验证上传文件后缀的合法性:

//表示只允许后缀为jpg/gif的文件上传。

if(smart.getFiles().getFile(0).getFileName().matches("^\\w+\\.(jpg|gif)$")){

}

4、批量上传

对upload3.jsp文件进行如下更改,其他的都不用改变,

<%@ page contentType="text/html" pageEncoding="utf-8"%>
<%@ page import="com.jspsmart.upload.*"%>
<%@ page import="kk.upload3.IPTimeStamp"%>
<html>
<head>
<title>文件上传3</title>
</head>
<body>
<%
request.setCharacterEncoding("utf-8");
SmartUpload smart=new SmartUpload();
smart.initialize(pageContext);
smart.upload();
String name=smart.getRequest().getParameter("uname");
IPTimeStamp its=new IPTimeStamp(request.getRemoteAddr());
for(int x=0;x<smart.getFiles().getCount();x++){
String ext=smart.getFiles().getFile(x).getFileExt();
String fileName=its.getIPTimeRand()+"."+ext;
smart.getFiles().getFile(x).saveAs(getServletContext().getRealPath("/")
+"upload"+java.io.File.separator+fileName);
}

%>

</body>
</html>

获得上传文件数量:smart.getFiles().getCount()。

 

三、FileUpload上传组件的使用

 

java web(四)文件上传与下载