百味皆苦 java后端开发攻城狮

struts2(文件上传和下载)

2019-06-07
百味皆苦

文件上传

  • select.jsp
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ page contentType="text/html;charset=UTF-8" import="java.util.*" language="java" pageEncoding="UTF-8" %>

<html>
<head>
    <title>upload_test</title>
</head>

<body>
    <s:form action="upload" method="post" theme="simple" enctype="multipart/form-data">
        输入帐号:<s:textfield name="uid"/><br>
        选择头像:<s:file name="headImage"/><br>
        <s:submit value="提交"/>
    
      <!--显示上传错误提示信息-->
     <s:fielderror/>
    
    </s:form>
</body>
</html>
  • action
  • 类型为java.io.File的xxx属性来封装文件域的信息
  • 类型为String的xxxFileName属性封装了该文件域对应的文本内容
  • 类型为String的xxxContentType属性封装了该文件域对应的文件类型
package action;

import com.opensymphony.xwork2.ActionSupport;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;
import java.io.File;
import java.io.IOException;

public class UploadAction extends ActionSupport {
    private String uid;                 // 封装帐号(uid)请求参数属性
    private File headImage;             // 封装上传文件域属性
    private String headImageContentType;     // 封装上传文件类型的属性
    private String headImageFileName;     // 封装上传文件属性

    public String getUid() {
        return uid;
    }
    public void setUid(String uid) {
        this.uid = uid;
    }

    public File getHeadImage() {
        return headImage;
    }
    public void setHeadImage(File headImage) {
        this.headImage = headImage;
    }

    public String getHeadImageContentType() {
        return headImageContentType;
    }
    public void setHeadImageContentType(String headImageContentType) {
        this.headImageContentType = headImageContentType;
    }

    public String getHeadImageFileName() {
        return headImageFileName;
    }
    public void setHeadImageFileName(String headImageFileName) {
        this.headImageFileName = headImageFileName;
    }

    public String execute() throws IOException {
        // 上传文件的保存位置在“/image”,该位置在tomcat服务器的“webapps”之中
        String  realpath= ServletActionContext.getServletContext().getRealPath("/image");

        // 声明文件目录image,如果文件名不存在就建一个呗~
        File file = new File(realpath);
        if(!file.exists()){
            file.mkdirs();
        }

        // 实现文件上传,也就是做了一个方法调用~
        FileUtils.copyFile(headImage,new File(file,headImageFileName));
        return SUCCESS;
    }
}
  • struts.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">

<struts>
    <!--指定国际化资源文件(下一章会讲到)-->
    <constant name="struts.custom.i18n.resources" value="messageResource"/>

    <!--设置Struts应用的解码集-->
    <constant name="struts.i18n.encoding" value="utf-8"/>
   
  <!-- ---  包配置  ---- -->
    <package name="default" namespace="/" extends="struts-default">
        <action name="upload" class="action.UploadAction">
            <result>/uploadSuccess.jsp</result>
        </action>
    </package>
</struts>
  • uploadSuccess.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<html>
<head>
    <title>上传初始页</title>
</head>
<body>
    上传成功!<br>

    <!--输入表单里的用户帐号属性-->
    用户帐号:<s:property value="uid"/><br>

    <!--根据上传文件名字,显示上传头像-->
    您的头像:<img src="<s:property value="'image/' + headImageFileName"/> " alt="图像无法显示"/>
</body>
</html>

文件过滤

  • Struts2提供了一个名为fileUpload拦截器,通过配置该拦截器可以轻松地实现文件过滤
  • allowTypes:该参数指定允许上传文件的类型,多个文件类型之间以英文逗号隔开
  • maximumSize:该参数指定允许上传文件的大小,单位是字节
  • 当文件过滤失败后,系统自动转入input逻辑视图,因此必须为Action配置名为input的逻辑视图
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">

<struts>
    <!--指定国际化资源文件(下一讲会讲到)-->
    <constant name="struts.custom.i18n.resources" value="messageResource"/>

    <!--设置Struts应用的解码集-->
    <constant name="struts.i18n.encoding" value="utf-8"/>

    <!--package中加入拦截器-->
    <package name="default" namespace="/" extends="struts-default">
        <interceptors>
            <!--配置拦截器栈(在拦截器章节有讲述)-->
            <interceptor-stack name="myStack">
                <!--配置fileUpload拦截器-->
                <interceptor-ref name="fileUpload">
                    <!--配置允许上传文件的类型(此处要注意的是png图片在ie浏览器中是image/x-png类型)-->
                    <param name="allowedTypes">image/x-png,image/bmp,image/gif,image/jpeg,image/jpg</param>
                    <!--配置允许上传文件大小拦截器,单位是字节(2的16次幂=65536(64k))-->
                    <param name="maximumSize">65536</param>
                </interceptor-ref>
                <interceptor-ref name="defaultStack"/>
            </interceptor-stack>
        </interceptors>

        <action name="upload" class="action.UploadAction">
            <!--使用拦截器栈-->
            <interceptor-ref name="myStack"/>
            <result>/uploadSuccess.jsp</result>

            <!--过滤失败,系统会转入input逻辑视图,这里配置其返回选择界面-->
            <result name="input">/select.jsp</result>
        </action>
    </package>
</struts>

常量配置

  • 上传文件时,系统默认使用web服务器的工作路径作为临时路径。为了避免文件上传时候使用Web服务器的工作路径作为临时路径,则应该设置struts.multipart.saveDir常量。该常量指定上传文件的临时保存路径
 <constant name="struts.multipart.saveDir" value="HOME/....(写上路径)..."/>
  • 还有一个文件上传的常量struts.multipart.maxSize。该常量指定struts.mutipart.maxSize。该常量指定在struts2文件上传中整个请求内容所允许的最大字节数,默认为2097152(即2MB)
<constant name="struts.multipart.maxSize" value="209971520"/>

文件下载

  • index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>


<html>
  <head>
    <title>test_download</title>
  </head>
  <body>
    请下载中文课件:<a href="downLoad.action?downPath=第一章节.doc"></a><br>
    请下载英文课件:<a href="downLoad.action?downPath=chapter01.doc"></a><br>
  </body>
</html>
  • DownLoadAction.java
  • 需要提供一个返回InputStream流方法,该输入流代表了被下载文件的入口
package action;

import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.ServletActionContext;
import util.MyUtil;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

public class DownLoadAction extends ActionSupport{

    private String downPath;        // 下载时的文件名
    private String contentType;     // 保存文件类型
    private String filename;        // 保存时的文件名

    public String getContentType() {
        return contentType;
    }

    public void setContentType(String contentType) {
        this.contentType = contentType;
    }

    public String getFilename() {
        return filename;
    }

    public void setFilename(String filename) {
        this.filename = filename;
    }

    public String getDownPath() {
        return downPath;
    }
    public void setDownPath(String downPath) {
        try {
            // 解决下载时候的中文文件乱码问题
            downPath = new String(downPath.getBytes("ISO-8859-1"),"UTF-8");
        }catch (UnsupportedEncodingException e){
            e.printStackTrace();
        }
        this.downPath = downPath;
    }

   /*
    *下载用的Action返回一个InputString实例,该方法对应Action配置
    *里面的result的inputName参数,值为inputString
    *
    */

   public InputStream getInputString(){
       return ServletActionContext.getServletContext().getResourceAsStream(downPath);
   }

   public String execute(){
       // 下载保存时的文件名和被下载的文件名一样
       filename = downPath;
       // 下载的文件路径,请在webapps目录下创建images
       downPath = "images/" + downPath;
       // 保存文件的类型

       contentType = "application/x-msdownload";

       /*
        *对下载的文件名按照UTF-8进行编码,解决下载窗口中的中文乱码问题
        * 其中,MyUtil是自己定义的一个类
        */

       filename = MyUtil.toUTF8String(filename);
       return SUCCESS;
   }
}
  • MyUtil.java
  • 该类中有一个静态方法toUTF8String实现对下载的文件名按照UTF-8进行编码,解决下载窗口中中文乱码的问题
package util;

import java.io.UnsupportedEncodingException;

public class MyUtil {
    // 对下载文件按照 UTF-8 进行编码

    public static String toUTF8String(String str){
        StringBuffer sb = new StringBuffer();
        int len = str.length();
        for (int i = 0; i < len; i++)
        {
            // 取出字符中的每个字符
            char c = str.charAt(i);
            // Unicode码值在0~255之间,不做处理
            if(c>=0 && c <= 255){
                sb.append(c);
            }else {
                // 转换 UTF-8 编码
                byte b[];
                try{
                    b = Character.toString(c).getBytes("UTF-8");
                }catch(UnsupportedEncodingException e){
                    e.printStackTrace();
                    b = null;
                }
                // 转换为%HH的字符串形式
                for(int j = 0;j < b.length ; j++){
                    int k = b[j];
                    if(k < 0){
                        k &= 255;
                    }
                    sb.append("%" + Integer.toHexString(k).toUpperCase());
                }
            }
        }
        return sb.toString();
    }
}
  • struts.xml
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">

<struts>
    <package name="default" namespace="/" extends="struts-default">
        <action name="downLoad" class="action.DownLoadAction">
            <!--结果类型为String-->
            <result type="stream">
				<!--指定被下载文件的文件类型-->
                <param name="contentType">${contentType}</param>
                
                <!--指定被下载文件的入口输入流,默认就是inputStream,它将会指示StreamResult通过
                  inputName属性值的getter和setter方法,如这里就是
                  getInputStream()来获取下载文件的内容,意味着Action
                  要有这个方法
                  -->
                <param name="inputName">inputStream</param>
                
                 <!--指定下载的文件名,默认为inline(在线打开),设置为attachment将会告诉浏览器下载
                     该文件,filename指定下载文件时的文件名,若未指定将会以浏览器
                     页面名作为文件名,如:以download.action作为文件名
                   -->
                <param name="contentDisposition">attachment;filename=${filename}</param>
                
                <!--指定下载文件的缓冲大小-->
                <param name="bufferSize">4096</param>

            </result>
        </action>
    </package>

文件下载次数

  • 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="default" extends="struts-default">    	
		<action name="downloadFileCount" class="example.struts2.DownloadFileCountAction">
			<result name="success" type="stream">
				<param name="contentType">${contentType}</param>
				<param name="inputName">inputStream</param>
				<param name="contentDisposition">
					attachment;filename=${fileName}
				</param>
			</result>
		</action>
    </package>
</struts>

  • DownloadFileCountAction
package example.struts2;

import java.io.InputStream;

import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;
import java.io.File;

public class DownloadFileCountAction extends ActionSupport{
	private String downloadPath;
	private String contentType;
	private String fileName;
	public String getDownloadPath() {
		return downloadPath;
	}
	public void setDownloadPath(String downloadPath) {
		this.downloadPath = downloadPath;
	}
	public String getContentType() {
		return contentType;
	}
	public void setContentType(String contentType) {
		this.contentType = contentType;
	}
	public String getFileName() {
		return fileName;
	}
	public void setFileNAme(String fileName) {
		this.fileName = fileName;
	}
	public String execute() throws Exception{
		downloadPath=ServletActionContext.getRequest().getParameter("download");
		int position=downloadPath.lastIndexOf("/");
		String downloadFilePath;
		if (position>0) {
			fileName=downloadPath.substring(position+1);
			downloadFilePath=downloadPath.substring(0,position+1);
		}
		else {
			fileName=downloadPath;
			downloadFilePath="";
		}
		int extPos= fileName.lastIndexOf(".");
		String contentTypeKey;
		if (extPos>0) {
			contentTypeKey="struts.contentType"+fileName.substring(extPos);
		}
		else {
			contentTypeKey="struts.contentType.txt";
		}
		
		contentType=getText(contentTypeKey);
		String counterFile= genNewFileName(downloadFilePath,fileName);
		setDownloadCount(counterFile);
		return SUCCESS;
	}
	public InputStream getInputStream() throws Exception{
		return ServletActionContext.getServletContext().getResourceAsStream(downloadPath);
		
	}
	private String genNewFileName(String filePath, String fileName) {
		// TODO Auto-generated method stub
		String serverRealPath=ServletActionContext.getServletContext().getRealPath(filePath)+"/DownloadCounter";
		File  dir=new File(serverRealPath);
		if (!dir.exists()) {
			dir.mkdir();
		}
		String downloadCountFile=serverRealPath+fileName+".txt";
		return downloadCountFile;
	}
	private void setDownloadCount(String fullFileName) throws Exception{
		// TODO Auto-generated method stub
		int curCount=1;
		File file=new File(fullFileName);
		if (file.exists()) {
			curCount=Integer.parseInt(FileUtils.readFileToString(new File(fullFileName)))+1;
		}
		FileUtils.writeStringToFile(file, Integer.toString(curCount));
		
	}
}

  • 在webRoot目录下创建文件夹Upload,在文件夹里创建文件Readme.txt
  • 启动项目访问downloadFileCount?download=/Upload/Readme.txt

Comments

Content