文件上传大概有三种方式:
1、上传到tomcat服务器 不推荐
缺点:1 有时候上传后需要刷新一遍,图片才会出来
2 重启tomcat图片可能会丢失
2、上传到指定文件目录,添加服务器与真实目录的映射关系,从而解耦上传文件与tomcat的关系
文件服务器
3、在数据库表中建立二进制字段,将图片存储到数据库 (淘汰)
缺点:1 占用空间大
2 查询耗时长
今天我们就来讲一讲第二种方式:
首先我们需要一个struts2项目,这里就用上次的strus2之增删改查项目。
紧接着我们需要上传图片的话就得需要一个需要一个相对应的页面:
clzUpload.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
新增修改
在clzList.jsp页面中添加跳转:
上传
配置struts-sy.xml:
/clzUpload.jsp
在控制器ClazzAction中添加方法:
package com.swx03.web;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import com.opensymphony.xwork2.ModelDriven;
import com.swx03.dao.ClazzDao;
import com.swx03.entity.Clazz;
import com.swx03.util.BaseAction;
import com.swx03.util.PageBean;
public class ClazzAction extends BaseAction implements ModelDriven{
private ClazzDao clazzDao = new ClazzDao();
private Clazz clz = new Clazz();
/**
* 上传图片所需参数
*/
private File file;//需要与上传的图片属性name一致
private String fileFileName;
private String fileContentType;
/**
* 查询
* @return
*/
public String list() {
PageBean pageBean = new PageBean();
pageBean.setRequest(request);//request 是从继承的BaseAction中获得
try {
this.result = clazzDao.list(clz, pageBean);
request.setAttribute("pageBean", pageBean);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "list";
}
/**
* 上传图片页面
* @return
*/
public String preUpload() {
try {
this.result = clazzDao.list(clz, null).get(0);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "preUpload";
}
public String Upload() {
//图片上传真实路径
String realDir = "D:/博客图片";
//服务器的请求目录
String serverDir = "/upload";
try {
FileUtils.copyFile(file, new File(realDir + "/" + fileFileName));
//把服务器请求目录和文件名保存到数据库
clz.setPic(serverDir+"/"+fileFileName);
this.clazzDao.edit(clz);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "toList";
}
/**
* 跳转编辑页面(与新增同一页面)
* 跳编辑页面时需要传递cid到后台进行查询并且将查询到的数据进行回显
* @return
*/
public String preSave() {
int cid = clz.getCid();
if(cid != 0) {
try {
this.result = clazzDao.list(clz, null).get(0);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return "preSave";
}
/**
* 增加
* @return
*/
public String add() {
try {
this.code = this.clazzDao.add(clz);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "toList";
}
/**
* 删除
* @return
*/
public String del() {
try {
this.code = this.clazzDao.del(clz);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "toList";
}
/**
* 修改
* @return
*/
public String edit() {
try {
this.code = this.clazzDao.edit(clz);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "toList";
}
@Override
public Clazz getModel() {
// TODO Auto-generated method stub
return clz;
}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public String getFileFileName() {
return fileFileName;
}
public void setFileFileName(String fileFileName) {
this.fileFileName = fileFileName;
}
public String getFileContentType() {
return fileContentType;
}
public void setFileContentType(String fileContentType) {
this.fileContentType = fileContentType;
}
}
在Tomcat中的server.xml配置映射关系:
这里我的真实路径是:
D:/博客图片
主页面:
上传页面:
上传成功!
查看真实路径文件夹:
如何实现文件上传:
主要是ClazzAction中的Upload方法里的 FileUtils.copyFile(file, new File(realDir + “/” + fileFileName));
public String Upload() {
//图片上传真实路径
String realDir = "D:/博客图片";
//服务器的请求目录
String serverDir = "/upload";
try {
FileUtils.copyFile(file, new File(realDir + "/" + fileFileName));
//把服务器请求目录和文件名保存到数据库
clz.setPic(serverDir+"/"+fileFileName);
this.clazzDao.edit(clz);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "toList";
}
那么它是如何实现的呢?
其实从本质上讲:
就是从本地读取文件写入到服务器中。
在ClazzAtion中重写copyFile方法:
private void copyFile(File source, File target) throws IOException {
BufferedInputStream in = new BufferedInputStream(new FileInputStream(source));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(target));
//定义一个缓冲的数组
byte [] bbuf = new byte[1024];
int len = 0;
while((len = in.read(bbuf))!=-1) {
out.write(bbuf, 0, len);
}
//关闭
in.close();
out.close();
}
使用重写后的方法:
/**
* 上传图片
* @return
*/
public String Upload() {
//图片上传真实路径
String realDir = "D:/博客图片";
//服务器的请求目录
String serverDir = "/upload";
try {
//将本地图片上传到真实存在的一个目录中(也就是从本地读取文件写入到服务器的目录)
//FileUtils.copyFile(file, new File(realDir + "/" + fileFileName));
copyFile(file, new File(realDir + "/" + fileFileName));
//把服务器请求目录和文件名保存到数据库
clz.setPic(serverDir+"/"+fileFileName);
this.clazzDao.edit(clz);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "toList";
}
结论是一样成功上传了图片!
那它又是如何截取到图片的呢?
这其中涉及到一个拦截器的问题:
比如写一个自己的拦截器并且使用:
package com.swx.interceptor;
import java.awt.event.InvocationEvent;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class OneInterceptor implements Interceptor{
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void init() {
// TODO Auto-generated method stub
}
@Override
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("拦截器赋值--");
invocation.invoke();
System.out.println("拦截器释放资源");
return null;
}
}
在struts-sy.xml定义并且使用:
/test.jsp