1 文件上传

html中通过可以向服务器上传文件。不过后台需要手动解析请求,比较复杂,所以可以使用smartupload或apache的fileupload组件进行文件的上传。smartupload据网友测试,在上传大文件时不稳定,所以还是使用fileupload的吧,毕竟apache出品。

本例子中使用的jar包:

commons-fileupload-1.3.2.jar

commons-io-2.5.jar(fileupload依赖)

前端jsp页面:

上传文件:

上传

重置

其中有几个需要注意的点:

form表单的enctype必须为"multipart/form-data"。

中必须有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 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进行校验。

enctype="multipart/form-data" οnsubmit="return check_file()">

上传文件:

type="submit" value="upload">上传

value="reset">重置

function check_file() {

var fileName = document.getElementById("uploadFile").value;

var suffix = fileName.substr(fileName.lastIndexOf(".") + 1);

if (suffix !== "exe") {

alert("只能上传exe文件");

return false;

}

}

对于第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属性可以防止页面跳转。

enctype="multipart/form-data" target="uploadFrame" οnsubmit="getStatus()">

上传文件:

type="submit" value="upload">上传

value="reset">重置

上传进度:

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);

}

最后 完整的程序UploadFile.zip

除了使用form表单上传文件这种方式,也可以利用html5的特性使用ajax上传文件。

下面是主要代码。

var formData = new FormData();

formData.append('file', $('#input')[0].files[0]);

$.ajax({

url: contextPath + '/file/upload?savedName=' + savedName,

type: 'POST',

data: formData,

cache: false,

contentType: false,

processData: false,

xhr: function () {

var xhr = $.ajaxSettings.xhr();

if (xhr.upload) {

xhr.upload.addEventListener("progress", function (evt) {

var percent = parseInt((evt.loaded / evt.total) * 100) + '%';

console.log(percent);

}, false);

return xhr;

}

}

}).done(function(e){})

首先初始化formData对象,然后将真正的file添加到formData里,然后创建一个ajax请求,type是POST,

data: formData,

cache: false,

contentType: false,

processData: false,

这几个属性很重要,具体解释请百度之。

上传进度则使用如下的方式获得:

xhr: function () {

var xhr = $.ajaxSettings.xhr();

if (xhr.upload) {

xhr.upload.addEventListener("progress", function (evt) {

var percent = parseInt((evt.loaded / evt.total) * 100) + '%';

console.log(percent);

}, false);

return xhr;

}

}

这里注意这个是浏览器上传的进度,在服务端还有写入磁盘的时间,所以即便达到100%了服务端可能也并没有完全完成保存操作,不过这个时间差可以忽略。

注意如果出于页面美化的目的,需要隐藏input框,那么一般会使用display:none这个css属性,但由于浏览器安全性的限制,这种方式无法奏效,这里提供一个tricky的方法,给input框设置一个position:absolute;top:-9999px;,这样既可以隐藏input,又可以触发选择文件的操作。

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的设置即可。

最终一个完整的文件上传下载的例子FileServer

java web fileupload_javaweb 文件上传(fileupload) 下载相关推荐

  1. java里面的文件上传与下载

    java里面的文件上传与下载 文件的上传与下载主要用到两种方法: 1.方法一:commons-fileupload.jar commons-io.jar apache的commons-fileuplo ...

  2. Java如何进行文件上传与下载

    Java文件上传与下载 在项目开发中难免遇到这样的问题,对于我这种小白,那只能寻求度娘的帮助拉,各种搜索和看博客文章,当实际运行时....哎,痛苦. 今日分享一波,望你所用,烦闷去之. 文件上传 首先 ...

  3. Web实现文件上传和下载

    目录 如何实现文件上传 文件上传相关的API Fileltem接口 DiskFileItemFactory类 ServletFileUpload类 [任务]实现文件上传 [任务目标] [实现步骤] 文 ...

  4. java 文件下载漏洞,文件上传和下载漏洞

    一.文件下载漏洞 1.需要寻找文件下载的路径进行构造一般链接形式: download.php?path= down.php?file= data.php?file= download.php?file ...

  5. Java Web实现文件上传(相机、相册)

    H5页面中通过JQuery的方式实现相机.相册.拍摄视频三种方式的文件上传,Java后端通过Servlet的方式来接收上传的文件并写入的服务端存储目录中. 前端HTML文件: <div clas ...

  6. java中ftp删除文件,Java 实现ftp 文件上传、下载和删除

    实现FTP相关功能 1.下载相应的jar包 commons-net-3.6.jar 2.代码实现 import java.io.File; import java.io.FileInputStream ...

  7. WEB超大文件上传与下载

    1.介绍enctype enctype 属性规定发送到服务器之前应该如何对表单数据进行编码. enctype作用是告知服务器请求正文的MIME类型(请求消息头content-type的作用一样) 1. ...

  8. springboot+web文件上传和下载

    一.首先安装mysql数据库,开启web服务器. 二.pom.xml文件依赖包配置如下: <?xml version="1.0" encoding="UTF-8&q ...

  9. Java Web项目中遇到的文件上传与下载问题

    (转发自:https://www.cnblogs.com/xdp-gacl/p/4200090.html)   在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中 ...

最新文章

  1. 美多商城之验证码(短信验证码2)
  2. 【教程】1、加载静态内容
  3. 关于在Webservice里使用LinqToSQL遇到一对多关系的父子表中子表需要ToList输出泛型而产生循环引用错误的解决办法!(转)...
  4. Java中加减乘除怎样写代码,【求助】怎样实现加减乘除 代码如下
  5. [导入]blog年终小结
  6. Android开发笔记(一百三十四)协调布局CoordinatorLayout
  7. count是java关键字吗_你是一直认为 count(1) 比 count(*) 效率高么?
  8. 通向AGI(通用人工智能)的另类书单
  9. 网络监控软件百络网警 v6.6b 家庭版 下载
  10. python识别手写文字_深度学习---手写字体识别程序分析(python)
  11. 使用unity实现计算器功能
  12. 发送webService请求BPM流程
  13. 经典的机器学习200道面试题及答案
  14. 国产DSP/ARM+复旦微ZYNQ/A7/K7 FPGA系列解决方案
  15. 数字抽奖小程序_发挥想象力,用 PowerBI 做抽奖小程序
  16. 电商平台之争,京东是如何脱颖而出的
  17. uniapp使用map地图组件
  18. C语言基础——运算符(定义变量、转义字符、输入输出语句、运算符、32个关键字)
  19. 聊聊C++任务定时器的设计与具体实现
  20. 菱形问号乱码怎么解决

热门文章

  1. 模块和包——Python
  2. OpenCV学习笔记总结
  3. php项目打不开DNS,电脑无法打开网页显示错误代码dns_probe_possible怎么解决?
  4. arduino analogread_Arduino编程语言教程,Arduino和单片机的区别
  5. stream流常用方法_Java8-Stream关键知识点
  6. android imageview 事件传递,Android 事件传递机制TextView,ImageView等没有默认clickable属性的View单独设置onTouch事件注意事项...
  7. linux 安装org2pg_Ora2Pg的安装和使用
  8. SynchronousQueue
  9. python笔记3:依次输入3个数排序打印(升序)
  10. 如何才能写出“高质量”的代码?