文件的上传和下载
上传
一,借助三方工具类实现上传文件
二,用springmvc框架中的类– 不过需要在springmvc.xml中配置上传文件解析器
下载
下载都是一样的,两个流,一个头
两个流:需要读取服务器端本地硬盘到内存的输入流,另一个是从服务器内存到客户端的输出流
一个头:设置下载的响应头
需要jar包:
commons-fileupload-1.3.1.jar
commons-io-2.2.jar
正文
在通过表单上传文件时,需要注意以下几点
1,post请求
2,输入框类型设置为file
3,把表单中属性修改 enctype=’multipart/form-data’多部件类型
该表单属性默认为 application/x-www-form-urlencoded,所以需要修改
<!-- 测试文件上传和下载 -->
<form action="${pageContext.request.contextPath}/file/FileUploadServlet"
method="post" enctype="multipart/form-data">
<p>用户名:<input type="text" name="uname" /> </p>
<p>密码:<input type="password" name="pwd" /> </p>
<p>照片:<input type="file" name="photo" /> </p>
<p> <input type="submit" value="注册"> </p>
</form>
Servlet部分
在服务器端 webapp下首先创建一个upload文件夹,用来存放上传的文件,需要考虑上传文件的重名问题
两种解决方案:
1,把上传的文件放到upload下的不同文件夹下(可以通过获取系统的毫秒值来命名)
2,把上传的文件重新命名(通过UUID类生成的随机字符命名)
这里采用第二种方式
public void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
/* String uname = request.getParameter("uname");
String password= request.getParameter("pwd");
String photo=request.getParameter("photo");*/
/* user.setName(uname);
user.setPassword(password);
System.out.println(user);*/
//借助其他三方工具jar包
//1,创建对象,创建保存字符串的临时文件及保存位置
DiskFileItemFactory factory=new DiskFileItemFactory();
//2,
ServletFileUpload upload=new ServletFileUpload(factory);
//创建一个user对象,封装信息
User user=new User();
//3,从字符串获取内容 分两步, 普通键值对 和 文件信息
try {
List<FileItem> items = upload.parseRequest(request);
//4,遍历集合,获取普通键值对信息
for(FileItem item :items) {
//获取键名
String fileName=item.getFieldName();
//判断是普通键值对信息
if(item.isFormField()) {
if("uname".equals(fileName)){
user.setName(item.getString());
}
if("password".equals(fileName)){
user.setPassword(item.getString());
}
}else {
//文件信息
//5,解决重名问题,生成随机字符串,采用随机字符+ 文件原名=新文件名
String uuid=UUID.randomUUID().toString();
//去掉uuid生成的随机字符中的 -, 以空串代替,实现去除
uuid=uuid.replace("-", "");
//获取原文件名,
String oldFileName=item.ge虑tName();
//考存带有路径的问题,做判断,有则截取,这里\需要转义,所以用\\
int index= oldFileName.lastIndexOf("\\");
//判断\路径分隔符的位置,如果为-1,则没有,如果有,则截取后面的文件名部分
if(index!=-1){
//有路径,则从后一位截取,获取文件名和后缀名
oldFileName.substring(index+1);
}
//拼接新文件名
String newFileName=uuid+"-"+oldFileName;
//6,获取upload的文件夹路径 ,这里相对于项目的路径,web项目也可说是相对于classes目录
String path= request.getServletContext().getRealPath("/upload");
//创建文件对象,指定文件夹下,文件名
File file=new File(path,newFileName);
//7,把文件信息写入到指定文件
item.write(file);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
下载
主要是通过response响应对象的输出流响应给对象
//下载功能
protected void download(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//一个头,两个流
//1,获取前台传过来的文件名
String fileName= request.getParameter("fileName");
//响应头 --固定格式 这里变量拼接,因此要转义filename后双引号
response.addHeader("content-Disposition", "attachment;filename=\""+fileName+"\"");
//获取该文件在服务器端的资源路径,因为是从服务器下载文件
String path=request.getServletContext().getRealPath("/upload");
//创建该下载文件的文件对象
File file=new File(path,fileName);
//2一个输入流,从服务器硬盘到内存
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));
//3,一个输出流,从服务器端内存到客户端,这里是多态,因OutputStream是接口,
//父类引用指向子类对象,实现动态绑定
OutputStream sos = response.getOutputStream();
int len=-1;
byte[] b=new byte[1024];
while((len=bis.read(b))!=-1) {
sos.write(b,0,len);
}
sos.close();
bis.close();
}
springmvc中实现上传
1,配置文件
<!-- 配置上传文件的解析器 -->
<!-- 实现上传时,这个解析器的id是固定名称multipartResolver -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 上传文件的大小设置,上传文件的大小不能超过参数的指定值,值单位是B,
这里设置的是10M,value中不可以用运算符,为了图方便,直接乘会报错(试过!) -->
<property name="maxUploadSize" value="10485760"></property>
<!-- 上传文件的默认编码格式 -->
<property name="defaultEncoding" value="utf-8"></property>
<!-- 类似懒加载的属性.可以定义该属性.让解析文件的时候再抛异常 -->
<property name="resolveLazily" value="true"></property>
</bean>
2,conroller中
这里对于上传文件的命名采用的是2者的组合方式,既创建文件夹,又修改文件名方式
/*这里要注意在前台表单中上传文件中input输入框的名字要和这里形参的MultipartFile的的一致,
才能实现匹配,获取上传数据*/
@RequestMapping("/user_upload.do")
public String fileUpload(User user,MultipartFile photo_str,
HttpServletRequest request,Model model) throws IllegalStateException, IOException{
//1,接收普通数据 user
//user这里只是接收表单中其他数据,将其封装到user类中的,方便处理数据
//2,接收文件数据 ,文件存储位置, 解决文件重名问题
if(photo_str!=null) {
//也得先在webapp下创建一个upload文件夹, 获取到upload位置,
//当然也可以配置tomcat的虚拟路径,直接存储到tomcat服务器中,这里是存储到项目中的
String path = request.getSession().getServletContext().getRealPath("/upload");
//获取旧文件名
String oldname = photo_str.getOriginalFilename();
//获取后缀名,最后一个.的下标
int index = oldname.lastIndexOf(".");
//截取,只获取 .后缀名 部分
String exname = oldname.substring(index);
//生成新的文件名
String uuid = UUID.randomUUID().toString().replace("-","");
//文件名和后缀拼接成新的文件名
String newName=uuid+exname;
//获取系统的当前毫秒值,用来做文件夹的名字
long ms=System.currentTimeMillis();
//和upload的绝对路径拼接,形成一个upload文件夹下的完整文件路径
path=path+"/"+ms;
//根据路径创建文件对象 --
File file=new File(path);
//创建文件夹,先判断是否存在,理论上是不会存在的
if(!file.exists()) {
file.mkdirs();
}
//创建文件夹下文件
file=new File(path,newName);
//将上传照片写入文件
photo_str.transferTo(file);
//user对象只是封装的图片的完整路径
user.setPhoto(file.getPath());
}
}
springmvc中实现下载
//文件下载
@RequestMapping("/user_fileDownload.do")
public String fileDownload(String fileName,
HttpServletResponse reponse,HttpServletRequest request) throws IOException{
//一个头,两个流
InputStream is=null;
OutputStream os=null;
//首先还是获取upload目录下的文件名路径
String path = request.getSession().getServletContext().getRealPath("/upload/"+fileName);
//根据获取的路径,读入文件到内存中
//从服务器端本地读入文件流
is=new BufferedInputStream(new FileInputStream(path));
//解决文件名在下载时遇到中文出现乱码问题----反向编码一次
//注意这个编码要在文件读取文件到输入流中之后,不然把文件名先改变编码后,
//在服务器端根据路径去读文件到输入流,会找不到这个文件,因为编码方式不同,文件名就变了,会报错
fileName =new String(fileName.getBytes("utf-8"),"iso8859-1");
reponse.addHeader("content-Disposition", "attachment;fileName="+fileName);
byte[] b=new byte[1024];
os=reponse.getOutputStream(); //写出到客户端的写出流
int len=-1;
while((len=is.read(b))!=-1){
os.write(b, 0, len);
}
os.close();
is.close();
}
学习总结,水平有限,如有错误,敬请指正,感激不尽!