文件上传与下载(关键词: struts2, 简单例子, 弹框下载)
此上传与下载是简化版, 在实际开发重要中要做数据校验: 此例以图片为例, 其他文件格式同理, 没有swf弹框选择下载目录
文件的上传下载原理:
上传:
已知条件: 1. 文件上传的目录位置已知或自定义; 2. 要上传的文件路径由用户指定
过程: 拿到要上传的文件路径-->绑定到文件-->绑定到输入流-->创建上传目录-->把目录绑定到文件-->把文件绑定到输出流-->边读边写-->反馈
注意: 其中, 第一个步骤和最后一个步骤是前端处理, 中间的所有步骤都要在后端封装成工具类
下载:
已知条件: 1. 要下载的文件路径; 2. 下载目录由用户指定
过程: 拿到用户指定的下载目录-->绑定到文件-->绑定到输出流-->拿到要下载的文件路径-->绑定到文件-->绑定到输入流-->边读边写-->反馈
注意: 同上, 中间过程在后端封装
总之, 文件上传和下载的条件是: 上传要提供文件的全路径, 下载要提供下载目录
文章出处:http://blog.csdn.net/gplihf/article/details/52128225
工程结构:

上传与下载=======================================
index.jsp(上传和下载同一jsp)
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>文件上传和下载</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<script type="text/javascript" src="script/jquery-1.7.2.min.js"></script>
<script type="text/javascript">
$(function() {
// 初始状态图片默认隐藏
$("#imgP").hide();
// 鼠标进入图片放大显示
$(".thumbs img").mouseover(function(){
$("#imgP").show();
var largePath=$(this).attr("src");
$("#largeImg").attr({
src:largePath
});
return false;
});
// 鼠标离开图片消失
$(".thumbs img").mouseout(function(){
// 鼠标离开时隐藏
$("#imgP").hide();
return false;
});
// 点击图片下载
$(".thumbs img").click(function() {
// 获取图片的路径
var imagepath=$(this).attr("src");
// 发送ajax请求
var url = "download.action";
var args = {"imagepath": imagepath, "time": new Date()}; // 发送的数据
$.post(url, args, function(data) {
if (data) {
alert("下载成功!");
}
});
});
});
</script>
</head>
<body>
<h2>文件上传</h2><!-- 可同时上传多张图片 -->
<form action="upload.action" method="post" enctype="multipart/form-data">
上传文件1:
<input type="file" name="upload" /><br>
上传文件2:
<input type="file" name="upload" /><br>
上传文件3:
<input type="file" name="upload" /><br>
<input type="submit" value="提交">
<font color="green">${result}</font>
</form>
<hr>
<!-- 文件下载, 鼠标滑过图片, 图片会自动放大显示, 鼠标离开会自动消失, 点击图片会下载, 下载完有提示 -->
<p class="thumbs">
<a href="javascript:void(0);" title="Image2"><img src="images/2.jpg" style="width: 80px;height:80px;"></a>
<a href="javascript:void(0);" title="Image3"><img src="images/3.jpg" style="width: 80px;height:80px;"></a>
<a href="javascript:void(0);" title="Image4"><img src="images/4.jpg" style="width: 80px;height:80px;"></a>
<a href="javascript:void(0);" title="Image5"><img src="images/5.jpg" style="width: 80px;height:80px;"></a>
<a href="javascript:void(0);" title="Image6"><img src="images/huge1.bmp" style="width: 80px;height:80px;"></a>
</p>
<h2>图片预览</h2>
<p id="imgP"><img id="largeImg" src="" alt="Large Image" style="width: 300px; height: 300px;"/></p>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="actions" namespace="/" extends="struts-default">
<!-- 图片上传 -->
<action name="upload" class="cn.itcast.file.action.UploadAction">
<result>index.jsp</result>
<!-- 配置拦截器限制上传文件类型及大小 -->
<interceptor-ref name="fileUpload">
<!-- 文件类型, 请查找链接:http://blog.csdn.net/wszxl492719760/article/details/8512542 -->
<param name="allowedTypes">text/plain,application/vnd.ms-excel,application/msword,image/bmp,image/x-png,image/gif,image/pjpeg</param>
<param name="maximumSize">2M</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
<!-- 图片下载 -->
<action name="download" class="cn.itcast.file.action.DownLoadAction">
<result>index.jsp</result>
</action>
</package>
</struts>
上传的action, UploadAction.java
package cn.itcast.file.action;
import java.io.File;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class UploadAction extends ActionSupport {
private static final long serialVersionUID = -3052296580244235815L;
private List<File> upload; // 上传的file控件的name属性名
private List<String> uploadContentType; // 上传的文件类型
private List<String> uploadFileName; // 上传的文件名
private String result; // 响应结果
@Override
public String execute() throws Exception {
String path = ServletActionContext.getServletContext().getRealPath("/images");
File file = new File(path);
if (!file.exists()) { // 如果目录不存在, 那么就创建一个目录
file.mkdir();
}
for (int i=0; i<upload.size(); i++) {
// 上传
FileUtils.copyFile(upload.get(i), new File(file, uploadFileName.get(i)));
}
result = "上传成功!";
return SUCCESS;
}
public List<File> getUpload() {
return upload;
}
public void setUpload(List<File> upload) {
this.upload = upload;
}
public List<String> getUploadContentType() {
return uploadContentType;
}
public void setUploadContentType(List<String> uploadContentType) {
this.uploadContentType = uploadContentType;
}
public List<String> getUploadFileName() {
return uploadFileName;
}
public void setUploadFileName(List<String> uploadFileName) {
this.uploadFileName = uploadFileName;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
}
下载的action, DownLoadAction.java
package cn.itcast.file.action;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class DownLoadAction extends ActionSupport {
private static final long serialVersionUID = -5754098251885840191L;
public String inputPath; // 文件下载路径 , 用不上
public String fileName; // 文件名, 用不上
@Override
public String execute() throws Exception {
// 1. 获取文件名
String imagepath = ServletActionContext.getRequest().getParameter("imagepath");
// imagepath=images/2.jpg
int index = imagepath.lastIndexOf("/");
// 从imagepath中截取出imageName
String imageName = imagepath.substring(index+1);
//如果是中文的文件名称需要转码
// imageName = URLEncoder.encode(imageName,"UTF-8");
// 输入流
String allImagePath = ServletActionContext.getServletContext().getRealPath("/") + imagepath;
File inpFile = new File(allImagePath); // 绑定到输入流文件
InputStream is = new FileInputStream(inpFile); // 绑定到输入流
// 2. 下载到哪里, 这里可以添加.swf动画, 让用户选择图片下载的目录, 输出流
String downLoadPath = ServletActionContext.getServletContext().getRealPath("/download");
File oupFile = new File(downLoadPath); // 为了判断目录是否存在, 先生成File
if (!oupFile.exists()) { // 如果目录不存在, 那么创建一个目录
oupFile.mkdir();
}
String allFilePath = downLoadPath + "\\" + imageName; // 下载后的文件路径
oupFile = new File(allFilePath);
OutputStream os = new FileOutputStream(oupFile); // 输出流
// 3. 开始文件流的读写操作
int len = 0; // 读到的字节大小
byte []bt = new byte[1024]; // 设置的每次读取的流的字节大小
while ((len = is.read(bt)) != -1) { // 说明有读到内容
os.write(bt, 0, len); // 边读边写
}
// 关闭流
is.close();
os.close();
// 这里简写
PrintWriter pw = ServletActionContext.getResponse().getWriter();
pw.print("success");
return SUCCESS;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getInputPath() {
return inputPath;
}
public void setInputPath(String inputPath) {
this.inputPath = inputPath;
}
}
========================================<完>===================
效果图:
主页面

文件目录:

上传目录:

下载目录:


=========================================================
以上是没有弹框的下载, 要使用弹框, 不能使用ajax发送请求, 否则一般情况下无法弹框, 当然也可以自己写工具类解决, 比较复杂, 这里不讨论.
index.jsp:
<form action="upload.action" method="post" enctype="multipart/form-data">
<a href="${pageContext.request.contextPath }/download.action?filepath=images/Excel1.xls">附件下载</a>
</form>
DownLoadAction.java:
1. 想办法获取文件全路径
2. 把文件全路径绑定到文件
3. 把文件绑定到输入流
// 弹框: 设置文件头, 告诉浏览器有文件要下载, 文件名要设置编码
response.setContentType("text/html;charset=UTF-8");
// String oldFileNameFilter = URLEncoder.encode(filepath, "UTF-8");
response.setHeader("Content-Disposition", "attachment;fileName=" + filename);
.............这里不需要设置下载目录, 由用户指定目录.............
// String allFilePath = downLoadPath + "\\" + filename; // 下载后的文件路径
// oupFile = new File(allFilePath);
// OutputStream os = new FileOutputStream(oupFile); // 输出流
// 获取输出流, 注意: 这里会报错: getOutputStream() has already been called for this response(解决方法在下面)
ServletOutputStream os = response.getOutputStream();
// 开始文件流的读写操作
int len = 0; // 读到的字节大小
byte []bt = new byte[1024]; // 设置的每次读取的流的字节大小
while ((len = is.read(bt)) != -1) { // 说明有读到内容
os.write(bt, 0, len); // 边读边写
}
// 关闭流
截图:

--------------------------------------------------------------------
报错: getOutputStream() has already been called for this response 解决方法
原因是上面已经使用OutputStream os = new FileOutputStream(oupFile);创建了一个输出流, 这里再创建就会报错, 不需要写下面的代码,
------------------------
PrintWriter pw = response.getWriter();
pw.write(json.toString());
pw.close();
------------------------
就直接使用os输出即可, 即
OutputStream os = new FileOutputStream(oupFile); 和 ServletOutputStream os = response.getOutputStream();
只能使用一个

浙公网安备 33010602011771号