Struts2 入门学习笔记(五)——上传下载

Struts2 入门学习笔记(五)——上传下载

一.简介


首先要明确为了能进行上传,必须将表单设为POST,并且添加属性enctype="multipart/form-data",只有这样才能进行传送。当然,关于在struts.properties配置文件中关于上传时的上传解析器在此不做讲解,有想看的可以去配置文件查找,主要由以下三种,一般默认第三种:
   
   
#指定使用COS的文件上传解析器
#struts.multipart.parser=cos
#指定使用Pell的文件上传解析器
#struts.multipart.parser=pell
#指定使用JakartaCommon-fileUpload文件上传解析器
#struts.multipart.parser=jakarta

二.单文件上传


1. 实现文件上传的Action
首先写一个表单jsp:
    
    
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
<s:form action="upload" enctype="multipart/form-data">
<s:textfield name="title" label="文件标题" />
<s:file name="upload" label="选择文件" />
<s:submit value="上传"/>
</s:form>
</body>
</html>
在struts2中框架负责解析HttpServletRequest请求的参数,包括文件域,Struts2使用File类型封装文件域,下面是Action:
    
    
package cn.sun.upload;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
 
import org.apache.struts2.ServletActionContext;
 
 
import com.opensymphony.xwork2.ActionSupport;
 
public class Upload extends ActionSupport{
//封装文件标题请求参数成员
private String title;
//封装上传文件域的成员变量
private File upload;
//封装上传文件类型
private String uploadContentType;
//封装上传文件名的属性
private String uploadFileName;
//直接在struts.xml中配置的成员变量
private String savePath;
//所有的getter/setter方法+下面这个(单独写是因为它的get是从struts.xml中取到的
public String getSavePath() {
return ServletActionContext.getServletContext().getRealPath(savePath);
}
public void setSavePath(String savePath) {
this.savePath = savePath;
}
@Override
public String execute() throws Exception {
//以服务器的文件保存地址和原文件名简历上传文件输出流
FileOutputStream fos = new FileOutputStream(getSavePath()+"\\"+getUploadFileName());
FileInputStream fis = new FileInputStream(getUpload());
byte[] buf = new byte[1024];
int len = 0;
while( ( len=fis.read(buf) ) > 0){
fos.write(buf, 0, len);
}
return SUCCESS;
}
}

下一步自然区设置配置文件,将这个action放入进去,同时将上面这个中savePath地址传入:
    
    
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="myPackage" extends="struts-default">
<action name="upload" class="cn.sun.upload.Upload">
<param name="savePath">/uploadFiles</param>
<result name="success">/page/success.jsp</result>
</action>
</package>
</struts>

这里顺便设置一个success页面用来显示接收到的文件:
    
    
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
This is my success page!<br>
文件标题:<s:property value=" + title"/><br>
文件为:<img src="<s:property value="'uploadFiles/'+uploadFileName"/>"/><br>
</body>
</html>
上述中文件名一致没有变化,建议真正保存的时候一定要用UUID工具将文件名唯一化保存,同时放弃文件名中的格式,这样保存的就是一个不可执行不可预览文件,提取时通过uploadFileContentType去还原文件类型。
文件不可轻易上传,有的文件万一有问题会影响系统的运行,或者有些东西是不允许上传的,或者文件大小要设限制等等,所以这里也需要一个过滤器来对上传文件进行一个过滤,通常有两种方法解决这个问题,一种是手动实现,在struts.xml文件中配置param放置允许上传类型,在action中提取后进行对比,有则上传,没有则返回异常或者错误界面;第二种是常见的过滤器设置,这里用拦截器实现文件的过滤,strtut2自带文件拦截器,我们只需要修改很少的代码就可以实现。。或者,还记得么,添加自己的拦截器,在自己的拦截器栈里加入自己的拦截器和默认拦截器栈,大功告成!
这里使用struts自带的拦截器,在struts.xml中添加:
  
  
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="myPackage" extends="struts-default">
<action name="upload" class="cn.sun.upload.Upload">
<!-- 配置fileUpload的拦截器 -->
<interceptor-ref name="fileUpload">
<!-- 配置允许的上传文件类型 -->
<param name="allowedTypes">image/png,image/gif,image/jpeg</param>
<!-- 配置允许的上传文件大小 -->
<param name="maximumSize">200000</param>
</interceptor-ref>
<!-- 配置系统默认拦截器栈 -->
<interceptor-ref name="defaultStack" />
<!-- 添加属性 -->
<param name="savePath">/uploadFiles</param>
<result name="input">/page/fail.jsp</result>
<result name="success">/page/success.jsp</result>
</action>
</package>
</struts>
来一个失败页面:
   
   
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head></head>
<body>
This is my fail page. <br>
<s:fielderror />
</body>
</html>
然后我们就可以去测定试一下了,结果上传成功

三.多文件上传

原理就是上面的那个,只不过多加了几次而已,这里只写几句话:
    
    
<title>Insert title here</title>
<script type="text/javascript">
function addFileUploadItem(){
var itemTdObj = document.getElementById("itemTdId");
//将原有的td中内容,添加一个字符串,设置回td
itemTdObj.innerHTML = itemTdObj.innerHTML + "<br/><span>选择文件:<input type=\"file\" name=\"image\" /></span>";
}
</script>
</head>
<body>
<!-- 使用JavaScript追加上传选择 -->
<a href="javascript:void(0)" onclick="addFileUploadItem()">添加上传选择</a>
<s:actionerror/>
<form action="${pageContext.request.contextPath}/uploadDemo02Action" method="post" enctype="multipart/form-data">
<table>
<tr>
<td id="itemTdId">
<span>选择文件:<input type="file" name="image" /></span>
</td>
</tr>
<tr>
<td><input type="submit" value="多文件上传"/></td>
</tr>
</table>
</form>
</body>

编写action提供字段及setter, 接收多个文件时,需要提供数组获得。

     
     
//提供接收的数据类型是数组即可。
//#1 文件内容
private File[] image;
//#2文件名称
private String[] imageFileName;
//#3文件类型
private String[] imageContentType;
//#4 setter方法
public void setImage(File[] image) {
this.image = image;
}
public void setImageFileName(String[] imageFileName) {
this.imageFileName = imageFileName;
}
public void setImageContentType(String[] imageContentType) {
this.imageContentType = imageContentType;
}

     
     
public void add() throws Exception {
//父目录
String parentDir = ServletActionContext.getServletContext().getRealPath("/WEB-INF/upload");
//遍历所有内容,并保存
for(int i = 0 ; i < image.length ; i ++){
// 1 文件内容
File singleImage = image[i];
// 2 文件名称
String singleFileName = imageFileName[i];
// 3 保存
File file = new File(parentDir , singleFileName);
FileUtils.copyFile(singleImage, file); // (流自动关闭,父目录自动创建)
}
}




    提供国际资源文件

    位置:当前类包下建立国际化文件/UploadDemo02Action.properties

    内容:

struts.messages.upload.error.SizeLimitExceededException=\u6587\u4EF6\u4E0A\u4F20\u5927\u5C0F\u8D85\u8FC7\u9650\u5B9A,\u5B9E\u9645\u5927\u5C0F{1}\uFF0C\u9650\u5B9A\u7684\u6700\u5927\u503C{0}

 properties 文件的 key 固定的,来自 struts2-core-2.3.15.3.jar!/org/apache/struts2/struts-messages.properties

四.下载

下载实现比较简单,有许多种方法,但是为什么用struts呢,因为有很好的控制性,权限之类的问题。
我们这里写一个实例来让大家明白下它的操作流程,首先编写action类:
     
     
package cn.sun.upload;
 
import java.io.InputStream;
 
import org.apache.struts2.ServletActionContext;
 
import com.opensymphony.xwork2.ActionSupport;
 
public class FileDownloadAction extends ActionSupport {
private String inputPath;
public void setInputPath(String inputPath) {
this.inputPath = inputPath;
}
//get方法在后面也有用
public InputStream getTargetFile() {
 
return ServletActionContext.getServletContext().getResourceAsStream(inputPath);
}
 
}

这里面我们定义了一个方法用来输出指定位置的文件流,只需要在其他地方使用该方法即可。
配置action类型的结果需要制定以下四个属性:
     
     
contentType 指定被下载文件的文件类型
inputName 指定被下载文件的入口输入流
contentDisposition 指定下载的文件名
bufferSize 下载缓冲大小
对应在struts.xml:
     
     
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="myPackage" extends="struts-default">
<action name="download" class="cn.sun.upload.FileDownloadAction">
<param name="inputPath">/uploadFiles/1.jpg</param>
<result type="stream">
<!-- 指定下载文件类型 -->
<param name="contentType">image/jpg</param>
<!-- 指定由getTargetFile()方法返回被下载的文件inputstream流 -->
<param name="inputName">targetFile</param>
<param name="contentDisposition">attachment;filename=1.jpg</param>
<param name="bufferSize">4096</param>
</result>
</action>
</package>
</struts>


中文乱码问题:
         当我们希望下载中文的文件名时,和刚才不一样,刚才直接写死了下载的文件地址和文件名,一般情况下在action中应该这样写就可以避免乱码:
     
     
package cn.sun.upload;
 
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
 
import org.apache.struts2.ServletActionContext;
 
import com.opensymphony.xwork2.ActionSupport;
 
public class FileDownloadAction extends ActionSupport {
private String inputPath;
public void setInputPath(String inputPath) {
this.inputPath = inputPath;
}
//
private String imageFileName;
public String getImageFileName() throws UnsupportedEncodingException {
return new String(imageFileName.getBytes(),"ISO-8859-1");
}
/
public InputStream getTargetFile() {
 
return ServletActionContext.getServletContext().getResourceAsStream(inputPath);
}
 
}

同理,在struts.xml中配置的时候刚才我们直接写得文件名,现在我们将获取到的文件名用表达式写出来而不是直接写汉语:
    
    
<action name="download" class="cn.sun.upload.FileDownloadAction">
<param name="inputPath">/uploadFiles/1.jpg</param>
<result type="stream">
<!-- 指定下载文件类型 -->
<param name="contentType">image/jpg</param>
<!-- 指定由getTargetFile()方法返回被下载的文件inputstream流 -->
<param name="inputName">targetFile</param>
<!--<param name="contentDisposition">attachment;filename=1.jpg</param>-->
<param name="contentDisposition">attachment;filename=${imageFileName}</param>
<param name="bufferSize">4096</param>
</result>
</action>
为什么我们在上面写一句${imageFileName}就可以收到文件名?这是因为在action中我们有一个getter方法,通过此方法就可以在xml中读取到数值,这是OGNL表达式






















深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值