栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JavaWeb文件上传与下载功能解析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JavaWeb文件上传与下载功能解析

在开发过程中文件的上传下载很常用。这里简单的总结一下:

1.文件上传必须满足的条件:

a、 页面表单的method必须是post 因为get传送的数据太小了
b、 页面表单的enctype必须是multipart/form-data类型的
c、 表单中提供上传输入域

代码细节: 客户端表单中:

第二步:遍历list

public class Up3Servlet extends HttpServlet {
 public void doPost(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
 request.setCharacterEncoding("UTF-8");
 String path = getServletContext().getRealPath("/up");
 //声明disk
 DiskFileItemFactory disk = new DiskFileItemFactory();
 disk.setSizeThreshold(1024*1024);
 disk.setRepository(new File("d:/a"));
 //声明解析requst的servlet
 ServletFileUpload up = new ServletFileUpload(disk);
 try{
  //解析requst
  List list = up.parseRequest(request);
  //声明一个list封装上传的文件的数据
  List> ups = new ArrayList>();
  for(FileItem file:list){
  Map mm = new HashMap();
  //获取文件名
  String fileName = file.getName();
  fileName = fileName.substring(fileName.lastIndexOf("\")+1);
  String fileType = file.getContentType();
  InputStream in = file.getInputStream();
  int size = in.available();
  //使用工具类
  FileUtils.copyInputStreamToFile(in,new File(path+"/"+fileName));
  mm.put("fileName",fileName);
  mm.put("fileType",fileType);
  mm.put("size",""+size);

  ups.add(mm);
  file.delete();
  }
  request.setAttribute("ups",ups);
  //转发
  request.getRequestDispatcher("/jsps/show.jsp").forward(request, response);

 }catch(Exception e){
  e.printStackTrace();
 }
 }
}

如上就是上传文件的常用做法。现在我们在来看看fileupload的其他查用API.

判断一个fileItem是否是file(type=file)对象或是text(type=text|checkbox|radio)对象:
boolean isFormField() 如果是text|checkbox|radio|select这个值就是true.

6.处理带说明信息的图片

public class UpDescServlet extends HttpServlet {
 public void doPost(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
 request.setCharacterEncoding("UTF-8");//可以获取中文的文件名
 String path = getServletContext().getRealPath("/up");
 DiskFileItemFactory disk = 
  new DiskFileItemFactory();
 disk.setRepository(new File("d:/a"));
 try{
  ServletFileUpload up = 
   new ServletFileUpload(disk);
  List list = up.parseRequest(request);
  for(FileItem file:list){
  //第一步:判断是否是普通的表单项
  if(file.isFormField()){
   String fileName = file.getFieldName();//=desc
   String value = file.getString("UTF-8");//默认以ISO方式读取数据
   System.err.println(fileName+"="+value);
  }else{//说明是一个文件
   String fileName = file.getName();
   fileName = fileName.substring(fileName.lastIndexOf("\")+1);
   file.write(new File(path+"/"+fileName));
   System.err.println("文件名是:"+fileName);
   System.err.println("文件大小是:"+file.getSize());
   file.delete();
  }
  }
 }catch(Exception e){
  e.printStackTrace();
 }
 }

}

7.文件上传的性能提升

在解析request获取FileItem的集合的时候,使用:

FileItemIterator it= up.getItemIterator(request);

比使用

List list = up.parseRequest(request);

性能上要好的多。

示例代码:

public class FastServlet extends HttpServlet {


 public void doPost(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
 request.setCharacterEncoding("UTF-8");
 String path = getServletContext().getRealPath("/up");
 DiskFileItemFactory disk = 
  new DiskFileItemFactory();
 disk.setRepository(new File("d:/a"));
 try{
  ServletFileUpload up = new ServletFileUpload(disk);
  //以下是迭代器模式
  FileItemIterator it= up.getItemIterator(request);
  while(it.hasNext()){
  FileItemStream item = it.next();
  String fileName = item.getName();
  fileName=fileName.substring(fileName.lastIndexOf("\")+1);
  InputStream in = item.openStream();
  FileUtils.copyInputStreamToFile(in,new File(path+"/"+fileName));
  }
 }catch(Exception e){
  e.printStackTrace();
 }

 }

}

8.文件的下载

既可以是get也可以是post。

public void doPost(HttpServletRequest req, HttpServletResponse resp)
  throws ServletException, IOException {
 req.setCharacterEncoding("UTF-8");
 String name = req.getParameter("name");
 //第一步:设置响应的类型
 resp.setContentType("application/force-download");
 //第二读取文件
 String path = getServletContext().getRealPath("/up/"+name);
 InputStream in = new FileInputStream(path);
 //设置响应头
 //对文件名进行url编码
 name = URLEncoder.encode(name, "UTF-8");
 resp.setHeader("Content-Disposition","attachment;filename="+name);
 resp.setContentLength(in.available());

 //第三步:开始文件copy
 OutputStream out = resp.getOutputStream();
 byte[] b = new byte[1024];
 int len = 0;
 while((len=in.read(b))!=-1){
  out.write(b,0,len);
 }
 out.close();
 in.close();
 }

在使用J2EE流行框架时,使用框架内部封装好的来完成上传下载更为简单:

Struts2完成上传.

在使用Struts2进行开发时,导入的jar包不难发现存在 commons-fileupload-1.3.1.jar 包。通过上面的学习我们已经可以使用它进行文件的上传下载了。但Struts2在进行了进一步的封装。

view


Controller

public class FileUploadAction extends ActionSupport
{
 private String username;

   //注意,file并不是指前端jsp上传过来的文件本身,而是文件上传过来存放在临时文件夹下面的文件
 private File file;

 //提交过来的file的名字
 //struts会自动截取上次文件的名字注入给该属性
 private String fileFileName;
 //getter和setter此时为了节约篇幅省掉
 @Override
 public String execute() throws Exception
 {
 //保存上传文件的路径
 String root = ServletActionContext.getServletContext().getRealPath("/upload");
 //获取临时文件输入流
 InputStream is = new FileInputStream(file);
 //输出文件
 OutputStream os = new FileOutputStream(new File(root, fileFileName));
 //打印出上传的文件的文件名
 System.out.println("fileFileName: " + fileFileName);
    // 因为file是存放在临时文件夹的文件,我们可以将其文件名和文件路径打印出来,看和之前的fileFileName是否相同
 System.out.println("file: " + file.getName());
 System.out.println("file: " + file.getPath());

 byte[] buffer = new byte[1024];
 int length = 0;

 while(-1 != (length = is.read(buffer, 0, buffer.length)))
 {
  os.write(buffer);
 }

 os.close();
 is.close();

 return SUCCESS;
 }
}

首先我们要清楚一点,这里的file并不是真正指代jsp上传过来的文件,当文件上传过来时,struts2首先会寻找struts.multipart.saveDir(这个是在default.properties里面有)这个name所指定的存放位置(默认是空),我们可以在我们项目的struts2中来指定这个临时文件存放位置。

  

 如果没有设置struts.multipart.saveDir,那么将默认使用javax.servlet.context.tempdir指定的地址,javax.servlet.context.tempdir的值是由服务器来确定的,例如:假如我的web工程的context是abc,服务器使用Tomcat,那么savePath就应该是%TOMCAT_HOME%/work/Catalina/localhost/abc_,临时文件的名称类似于upload__1a156008_1373a8615dd__8000_00000001.tmp,每次上传的临时文件名可能不同,但是大致是这种样式。而且如果是使用Eclipse中的Servers里面配置Tomcat并启动的话,那么上面地址中的%TOMCAT_HOME%将不会是系统中的实际Tomcat根目录,而会是Eclipse给它指定的地址,例如我本地的地址是这样的:/home/wang/EclipseJavaCode/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/work/Catalina/localhost/abc/upload__1a156008_1373a8615dd__8000_00000001.tmp。

Struts2完成下载.

struts2的文件下载更简单,就是定义一个输入流,然后将文件写到输入流里面就行,关键配置还是在struts.xml这个配置文件里配置:

public class FileDownloadAction extends ActionSupport
{
 //要下载文件在服务器上的路径
 private String path;
 //要下载文件的文件名
 private String downloadFileName;
 //写入getter和setter
 public InputStream getDownloadFile()
 {
 return ServletActionContext.getServletContext().getResourceAsStream(path);
 }

 @Override
 public String execute() throws Exception
 {
 //当前action默认在valuestack的栈顶
 setDownloadFileName(xxx);
 return SUCCESS;
 }
}

action只是定义了一个输入流downloadFile,然后为其提供getter方法就行,接下来我们看看struts.xml的配置文件:

 
  
 attachment;fileName="${downloadFileName}"
 downloadFile
  
 

struts.xml配置文件有几个地方我们要注意,首先是result的类型,type一定要定义成stream类型_,告诉action这是文件下载的result,result元素里面一般还有param子元素,这个是用来设定文件下载时的参数,inputName这个属性就是得到action中的文件输入流,名字一定要和action中的输入流属性名字相同,然后就是contentDisposition属性,这个属性一般用来指定我们希望通过怎么样的方式来处理下载的文件,如果值是attachment,则会弹出一个下载框,让用户选择是否下载,如果不设定这个值,那么浏览器会首先查看自己能否打开下载的文件,如果能,就会直接打开所下载的文件,(这当然不是我们所需要的),另外一个值就是filename这个就是文件在下载时所提示的文件下载名字。在配置完这些信息后,我们就能过实现文件的下载功能了。

SpringMVC完成上传:

view于struts2示例中的完全一样。此出不在写出。

Controller:

@Controller
@RequestMapping(value="fileOperate")
public class FileOperateAction {
 @RequestMapping(value="upload")
 public String upload(HttpServletRequest request,@RequestParam("file") MultipartFile photoFile){
 //上传文件保存的路径
 String dir = request.getSession().getServletContext().getRealPath("/")+"upload";
 //原始的文件名
 String fileName = photoFile.getOriginalFilename();   //获取文件扩展名
 String extName = fileName.substring(fileName.lastIndexOf(".")); 
 //防止文件名冲突,把名字小小修改一下
 fileName = fileName.substring(0,fileName.lastIndexOf(".")) + System.nanoTime() + extName; 
 FileUtils.writeByteArrayToFile(new File(dir,fileName),photoFile.getBytes());
 return "success";
 }
 }

SpringMVC完成下载:

 @RequestMapping("/download")
 public String download(String fileName, HttpServletRequest request,
  HttpServletResponse response) {
 response.setCharacterEncoding("utf-8");
 response.setContentType("multipart/form-data");
 response.setHeader("Content-Disposition", "attachment;fileName="
  + fileName);
 try {
  InputStream inputStream = new FileInputStream(new File(文件的路径);

  OutputStream os = response.getOutputStream();
  byte[] b = new byte[2048];
  int length;
  while ((length = inputStream.read(b)) > 0) {
  os.write(b, 0, length);
  }

  // 这里主要关闭。
  os.close();

  inputStream.close();
 } catch (FileNotFoundException e) {
  e.printStackTrace();
 } catch (IOException e) {
  e.printStackTrace();
 }
  // 返回值要注意,要不然就出现下面这句错误!
  //java+getOutputStream() has already been called for this response
 return null;
 }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/149718.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号