serlvet进行文件上传
文件上传于下载是web应用的常见功能,本文主要书写了servlet的文件上传方法
基于servlet文件上传的方式有两种:
1.基于工具jar包的形式
2.servlet3.0提供的形式
一、使用第三方jar提供的工具类实现servlet文件上传
文件上传基于form表单实现,就是在一个FORM中提交相应的信息,和之前我们的提交的注册信息之类的表单是不同的,所以要先改变一下FORM的属性,enctype="multipart/form-data“,这个属性告诉服务器,我们是要提交文件了,而不是一个表单。将文件对应的内容以二进制的形式传递给后台
<input type=“file” />这是表单中用来选择上传文件用的,在表单中有这个元素后,会会自动生成一个输入框和一个按钮
我们主要使用两个jar包 commons-fileupload.jar commons-io.jar
主要使用的如下:
FileItem-------DiskFileItemFactory-----ServletFileUpload
作用:
FileItem 用来封装表单中的元素和数据。
ServletFileUpload 处理表单数据,将数据封装到 FileItem 对象中。
DiskFileItemFactory FileItem 对象的工厂,可以设定缓冲区大小和存放临时文件目录。
ServletFileUpload 处理上传的文件的数据,优先保存在缓冲区,如果数据超过了缓冲区大小,则保存到硬盘上,存储在DiskFileItemFactory指定目录下的临时文件。数据都接收完后,它再在从临时文件中将数据写入到上传文件目录下的指定文件中,并删除临时文件。
上传页面
通过form表单进行文件上传,需要在form表单中设置enctype="multipart/form-data" 并且将提交方式设置为post
<h3>会员上传资料</h3>
<form action="/upload" method="post" enctype="multipart/form-data">
姓名: <input type="text" name="uname"> <br>
文件: <input type="file" name="ufile"> <br>
<input type="submit" value="提交资料">
</form>
接受上传的servlet服务文件相应doPost方法
//使用FileItem工场类创建相应工场对象
FileItemFactory factory = new DiskFileItemFactory();
//创建servlet文件上传对象并将指定工场对象传入
ServletFileUpload fileUpload = new ServletFileUpload(factory);
//声明文件集合
List<FileItem> parseRequest = null;
//声明其他数据保存的map集合
hashMap<String,String>map=new HashMap<>();
try {
//使用servlet文件上传对象解析请求返回文件集合
parseRequest = fileUpload.parseRequest(request);
// 遍历文件对象集合 获取数据
for (FileItem fileItem : parseRequest) {
// 判断数据类型是不是普通的form表单字段
if (!fileItem.isFormField()) {
// 获取上传文件的文件名
String fileName = fileItem.getName();
//使用上传文件创建输入流
InputStream fileStream = fileItem.getInputStream();
// 使用UUID+文件名的方式生成保存文件的名称,避免文件重名
String realFileName = UUID.randomUUID().toString() + "-" + fileName;
// 定义保存的父路径
File fileFatherPath=new File("F://Upload");
//创建父路径 避免路径不存在保错
fileFatherPath.mkdirs();
// 创建要保存的文件
File file = new File(fileFatherPath, realFileName);
// 创建输出流
OutputStream out = new FileOutputStream(file);
// 创建字节缓存
byte[] buffer = new byte[1024];
int len = -1;
// 一次读取1kb(1024byte),返回-1表明读取完毕
while ((len = fileStream.read(buffer)) != -1) {
// 一次写入1kb(1024byte)
out.write(buffer, 0, len);
}
// 冲刷流资源
out.flush();
// 关闭流
out.close();
fileStream.close();
}else{
//如果是普通字段获取name与value存储至map集合中
map.put(fileItem.getFieldName(), fileItem.getString());
}
}
} catch (Exception e) {
e.printStackTrace();
}
多文件上传只需要在input处添加multiple属性 设置file可以选择上传多个文件
二、servlet3.0提供的源方式
servlet3.0提供的源方式的文件上传无需第三方jar包,但页面请求方式以及请求数据格式相同
Part:主要工具类,从前台获取的上传文件内容流存储位置Servlet3.0将multipart/form-data的POST请求封装成Part,通过Part对上传的文件进行操作,之后再part对象中获取输入流之后通过流操作保存数据
servlet是通过使用@MultipartConfig注解来完成文件的上传(用来标志当前servlet是处理文件上传的servlet)
@MultipartConfig
@WebServlet(name = "FileUploadServlet",urlPatterns = "/upload")
public class FileUploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Part part = request.getPart("ufile");
//Servlet3.0将multipart/form-data的POST请求封装成Part,通过Part对上传的文件进行操作。
//Servlet3没有提供直接获取文件名的方法,需要从请求头中解析出来
//获取请求头,请求头的格式:form-data; name="file"; filename="snmp4j--api.zip"
String disposition = part.getHeader("Content-Disposition");
//从请求头中获取文件后缀
String suffix = disposition.substring(disposition.lastIndexOf("."),disposition.length()-1);
//随机的生存一个32的字符串 用于避免上传文件同名
String filename = UUID.randomUUID()+suffix;
//获取上传的文件名
InputStream is = part.getInputStream();
//动态获取服务器的路径
String serverpath = request.getServletContext().getRealPath("upload");
new File(serverpath).mkdirs();
System.out.println(serverpath);
FileOutputStream fos = new FileOutputStream(serverpath+"/"+filename);
byte[] bty = new byte[1024];
int length =0;
while((length=is.read(bty))!=-1){
fos.write(bty,0,length);
}
fos.close();
is.close();
}
多文件上传的方式是通过修改获取part方法的形式实现的
Collection<Part> parts = request.getParts();
for (Part p : parts) {
.....
}
文件下载
就是在响应中设置响应类型之后,以流的形式将文件发送至客户端
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
// request通过getParameter得到filename这个参数的值
File f=new File("f://cxk.gif");
//设置content-disposition响应头控制浏览器以下载的形式打开文件,中文文件名要使用URLEncoder.encode方法进行编码,否则会出现文件名乱码
response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode("cxk.gif", "UTF-8"));
FileInputStream fis=new FileInputStream(f);
BufferedInputStream bis=new BufferedInputStream(fis);
byte []b=new byte[2048];
int len=-1;
ServletOutputStream outputStream = response.getOutputStream();
while((len=bis.read(b))!=-1) {
outputStream.write(b,0,len);
}
bis.close();
}