文件上传与下载(关键词: 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(); 
只能使用一个

 

posted @ 2017-05-20 01:56  半生戎马,共话桑麻、  阅读(181)  评论(0)    收藏  举报
levels of contents