javaweb 文件上传(fileupload) 下载
来源:互联网 发布:truelicense源码包 编辑:程序博客网 时间:2024/06/15 04:27
1 文件上传
html中通过<input type="file"/>可以向服务器上传文件。不过后台需要手动解析请求,比较复杂,所以可以使用smartupload或apache的fileupload组件进行文件的上传。smartupload据网友测试,在上传大文件时不稳定,所以还是使用fileupload的吧,毕竟apache出品。
本例子中使用的jar包:
- commons-fileupload-1.3.2.jar
- commons-io-2.5.jar(fileupload依赖)
前端jsp页面:
<div class="upload"> <form action="UploadFileServlet" method="POST" enctype="multipart/form-data"> 上传文件:<input type="file" name="uploadFile"> <input type="submit" value="upload">上传 <input type="reset" value="reset">重置 </form> </div>
其中有几个需要注意的点:
- form表单的enctype必须为"multipart/form-data"。
- <input type="file" name="uploadFile"/> 中必须有name属性,因为在fileupload中会根据fieldName解析上传的文件。
- method必须为POST方法。
- 如果多文件上传的话,file类型的name必须为不同的名称。
服务端需要建立一个UploadFileServlet来处理请求。
关键的doPost方法:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub // 首先检测是否是文件上传,主要依据enctype的值来判定 if (!ServletFileUpload.isMultipartContent(request)) { PrintWriter writer = response.getWriter(); writer.write("Error 不是文件上传,表单必须包含 enctype='multipart/form-data'"); writer.flush(); writer.close(); return; } DiskFileItemFactory factory = new DiskFileItemFactory(); // 设置在内存中的缓存大小,如果超过了则保存到临时文件。 factory.setSizeThreshold(MEMORY_THRESHOLD); System.err.println(System.getProperty("java.io.tmpdir")); // 设置临时文件夹的目录 factory.setRepository(new File(System.getProperty("java.io.tmpdir"))); ServletFileUpload upload = new ServletFileUpload(factory); // 设置单个文件大小的最大值 upload.setFileSizeMax(MAX_FILE_SIZE); // 设置上传文件总量的最大值,包括所有文件和表单的总和 upload.setSizeMax(MAX_REQUEST_SIZE); File uploadDir = new File(UPLOAD_PATH); if (!uploadDir.exists()) { uploadDir.mkdir(); } try { // 解析request List<FileItem> formItems = upload.parseRequest(request); if (formItems != null && formItems.size() > 0) { for (FileItem item : formItems) { // 如果不是普通的formField则就是上传的文件 if (!item.isFormField()) { String fileName = item.getName(); File storeFile = new File(UPLOAD_PATH + File.separator + fileName); System.err.println(storeFile.getAbsolutePath()); item.write(storeFile); item.delete(); } else { System.err.println(item.getString()); } } } request.setAttribute("message", "成功"); request.getRequestDispatcher("result.jsp").forward(request, response); } catch (Exception e) { // TODO: handle exception request.setAttribute("message", e.getMessage()); request.getRequestDispatcher("result.jsp").forward(request, response); e.printStackTrace(); return; } }
这样即可实现文件的上传。
需要改进的地方
- 没有上传进度
- 限制文件大小
- 限制文件类型
对于第2点,可以利用fileupload的抛出异常解决。
catch(FileUploadBase.FileSizeLimitExceededException e){ request.setAttribute("message", "单个文件大小超过限制"); request.getRequestDispatcher("result.jsp").forward(request, response); e.printStackTrace(); return; } catch(FileUploadBase.SizeLimitExceededException e){ request.setAttribute("message", "上传文件总大小超过限制"); request.getRequestDispatcher("result.jsp").forward(request, response); e.printStackTrace(); return; }
对于第3点,可以在页面用js进行校验。
<form action="UploadFileServlet" method="POST" enctype="multipart/form-data" onsubmit="return check_file()"> 上传文件:<input type="file" name="uploadFile" id="uploadFile"> <input type="submit" value="upload">上传 <input type="reset" value="reset">重置 </form> <script> function check_file() { var fileName = document.getElementById("uploadFile").value; var suffix = fileName.substr(fileName.lastIndexOf(".") + 1); if (suffix !== "exe") { alert("只能上传exe文件"); return false; } } </script>
对于第1点,fileupload可以添加监听器,监听上传进度。
//设置上传进度的监听器 ProgressListener progressListener = new ProgressListener() { public void update(long pBytesRead, long pContentLength, int pItems) { System.out.println("We are currently reading item " + pItems); if (pContentLength == -1) { System.out.println("So far, " + pBytesRead + " bytes have been read."); } else { System.out.println("So far, " + pBytesRead + " of " + pContentLength + " bytes have been read."); uploadPercent = (double) pBytesRead / pContentLength; System.err.println(uploadPercent); } } }; upload.setProgressListener(progressListener);
虽然服务端添加了监听器,可以在console或者Log里打印上传进度,但我们想要的是让用户看到上传进度。所以需要把进度返回给用户。
要解决的问题主要有两个:
- 进度信息如何保存
前台如何获取
其中的一种方案是利用session。我们将上传进度保存在session里,前台通过ajax方法定时获取上传的进度,因为每个用户是一个session,不同的用户session不同。这样当不同的用户同时上传文件时,依然可以正确的获得上传进
度,不会获取到其他用户上传文件的进度。
具体首先有一个简单的保存上传进度的实体类:public class UploadStatus {private double percent;public double getPercent() { return percent;}public void setPercent(double percent) { this.percent = percent;}}
然后有一个监听的类,实现了ProgressListener接口
public class UploadListener implements ProgressListener{ private UploadStatus status; public UploadListener(UploadStatus status) { // TODO Auto-generated constructor stub this.status = status; } @Override public void update(long pBytesRead, long pContentLength, int pItems) { // TODO Auto-generated method stub double uploadPercent = (double) pBytesRead / pContentLength; status.setPercent(uploadPercent); }}
在doPost方法中:
//设置上传进度的监听器 UploadStatus status = new UploadStatus(); UploadListener listener = new UploadListener(status); upload.setProgressListener(listener); request.getSession(true).setAttribute("uploadStatus", status);
最后在doGet方法中,返回上传进度。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); response.setHeader("Cache-Control", "no-store"); response.setDateHeader("Expires", 0); response.setHeader("Pragrma", "no-cache"); PrintWriter writer = response.getWriter(); UploadStatus status = (UploadStatus)(request.getSession().getAttribute("uploadStatus")); if(status != null){ writer.write("上传进度:" + status.getPercent()); }else{ writer.write("没有上传信息"); } writer.flush(); writer.close(); }
当用户上传时可以访问doGet方法即可获取进度。
前台页面可以这样写:
其中form的target属性可以防止页面跳转。
<body><iframe width=0 height=0 name="uploadFrame"></iframe> <form action="UploadFileServlet" method="POST" enctype="multipart/form-data" target="uploadFrame" onsubmit="getStatus()"> 上传文件:<input type="file" name="uploadFile" id="uploadFile"> <input type="submit" value="upload">上传 <input type="reset" value="reset">重置 </form> <span>上传进度:</span><span id="progress"></span> <script src="jquery-1.11.2.js"></script> <script> var finished ; function check_file() { var fileName = document.getElementById("uploadFile").value; var suffix = fileName.substr(fileName.lastIndexOf(".") + 1); if (suffix !== "exe") { //alert("只能上传exe文件"); //return false; } finished = false; return true; } function getStatus(){ finished = false; console.log("finished = " + finished) showStatus(); } function showStatus(){ console.log("showstatus finished = " + finished) if(finished === true) return; $.ajax({ url:'UploadFileServlet', type:'GET', success:function(data){ $('#progress').text(data); if(data == '1.0'){ finished = true; } }, error:function(data){ alert(data); } }); setTimeout(showStatus,1000); } </script></body>
最后 完整的程序UploadFile.zip
2 文件下载
文件下载相对比较简单
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String id = request.getParameter("id"); //app.properties 路径 DFileItem dao = new DFileItem(); String basePath = request.getSession().getServletContext().getRealPath(""); String configPath = basePath+Constants.CONFIG_PATH; String uploadPath = Configuration.getInstance(configPath).getProperty(Constants.FILE_STORAGE_PATH); FileItem item = dao.queryFileItem(id); if(item == null){ PrintWriter writer = response.getWriter(); writer.write("文件已经被删除"); writer.close(); return; } String name = item.getFileName(); response.setContentType("application/octet-stream"); String downloadName = URLEncoder.encode(name,"UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-Disposition", "attachment;filename*=utf-8'zh_cn'"+downloadName); File file = new File(uploadPath+item.getUploadTime()); response.setContentLength((int)file.length()); FileInputStream in = new FileInputStream(file); OutputStream out = response.getOutputStream(); byte[] buffer = new byte[8192]; int len = 0; while((len = in.read(buffer)) != -1){ out.write(buffer, 0, len); } out.flush(); out.close(); in.close(); }
注意response 的contentType和header的设置即可。
- javaweb 文件上传(fileupload) 下载
- javaweb 文件上传(fileupload) 下载
- commons-fileupload文件上传、下载
- commons-fileupload文件上传、下载
- javaweb FileUpload 图片文件上传示例
- javaWeb实战教程5-fileupload文件上传
- javaweb中运用fileupload上传文件
- javaweb中的文件上传之fileupload组件
- JavaWeb 文件 上传 下载
- JavaWeb文件上传、下载
- JavaWeb 文件 上传 下载
- 使用fileupload上传文件,并提供下载
- common-fileupload文件上传及下载
- common-fileupload文件上传及下载
- common-fileupload文件上传及下载
- Jsp 使用 fileupload 文件上传和下载
- 文件上传与下载(FileUpload组件)
- 文件上传与下载(Commons-fileupload)
- 备战美赛,这些你应该知道的知识点
- 月薪多少才算80后中的"人生赢家"?他们的经济、婚姻、生活方式是怎样的
- 如何在ngbtabset切换tab时不销毁页面只做隐藏
- CQOI2014数三角形
- 如何进行字符串拷贝
- javaweb 文件上传(fileupload) 下载
- 11.30decision tree&logostic rgression
- Quartz-Hello World
- 使用 RequireJS 优化 Web 应用前端
- Java集合框架上机练习题-1
- 【牛腩】VS2012 打开项目提示asp.net 4.0尚未在web服务器上注册
- Python数据分析之pandas ,part1
- 复数
- 【前端】前端环境的配置与安装