Struts2 圖片上傳、縮放、剪切處理 第一節
1、技術目標:
- 爲項目"影片管理"加入圖片上傳功能
- 使用struts2完成圖片上傳
- 將上傳的圖片重命名並保存到web服務器
注意:本文所用項目爲"影片管理",參看
http://hotstrong.iteye.com/blog/1156785
提示:本文示例項目已提供下載
2、MySQL數據表film(影片表)加入列imgurl(影片海報圖片鏈接),執行如下SQL:
ALTER TABLE film ADD imgurl VARCHAR(200) DEFAULT NULL;
3、POJO類Film加入屬性imgurl,代碼如下:
BaseDomain爲所有POJO類的基類,
package com.xxx.pojo;
public class BaseDomain {
/**
* id
*/
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}@Override
public String toString() {
return "BaseDomain [id=" + id + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BaseDomain other = (BaseDomain) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}
Film(影片類),
package com.xxx.pojo;
public class Film extends BaseDomain {
// Fields
private String fname;//影片名稱
private String imgurl;//海報圖片url
// Constructors
/** default constructor */
public Film() {
}
// Property accessors
public String getFname() {
return this.fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getImgurl() {
return imgurl;
}
public void setImgurl(String imgurl) {
this.imgurl = imgurl;
}
}
4、FilmMapper.xml中,添加影片與修改影片的SQL語句中加入對imgurl字段的操作,如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xxx.dao.temp.FilmMapper"> <!-- 查詢所有電影信息,對應FilmMapper接口中的getAllFilm方法 --> <select id="getAllFilm" resultType="Film"> select * from film </select> <!-- 按電影編號查詢電影信息,對應FilmMapper接口中的getFilmById方法 --> <select id="getFilmById" parameterType="int" resultType="Film"> select * from film where id=#{id} </select> <!-- 按要求排序 --> <select id="getAllFilmOrder" parameterType="map" resultType="Film"> select * from film where 1 = 1 <if test="orderKey != null"> order by ${orderKey} </if> </select> <!-- 添加影片 --> <insert id="insertFilm" parameterType="Film" keyProperty="id" useGeneratedKeys="true"> insert into film (fname, imgurl) values (#{fname}, #{imgurl}); </insert> <!-- 修改影片 --> <update id="updateFilm" parameterType="Film"> update film <trim prefix="set" suffixOverrides=","> <if test="fname != null"> fname = #{fname}, </if> <if test='imgurl != null and imgurl != ""'> imgurl = #{imgurl} </if> </trim> where id = #{id} </update> <!-- 刪除影片 --> <delete id="deleteFilm" parameterType="int"> delete from film where id = #{id} </delete> </mapper>
5、在WebRoot(頁面路徑)下創建文件夾images,放一張提示圖片error.gif(示例項目中提供),在影片無海報圖片時顯示
6、在添加、修改影片頁面(insertFilm.jsp、updateFilm.jsp)中
加入文件選擇對話框並設置表單屬性enctype,如下:
添加影片頁面效果圖:
insertFilm.jsp代碼,
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8" %>
<%@taglib uri="/struts-tags" prefix="s" %>
<%
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>
<title>添加影片</title>
</head>
<body>
<%--
enctype屬性:規定在發送到服務器之前應該如何對錶單數據進行編碼
multipart/form-data值:不對字符編碼,在使用包含文件上傳控件的表單時必須使用該值
--%>
<s:form action="/film/insertFilm" method="post" enctype="multipart/form-data">
影片名稱:<s:textfield name="fname" value="" /><br />
<%--文件選擇框 --%>
影片海報:<s:file id="imgPhoto" name="imgPhoto"/><br />
<s:submit value=" 添加 "></s:submit>
</s:form>
</body>
</html>
修改頁面效果圖:
updateFilm.jsp代碼,
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8" %>
<%@taglib uri="/struts-tags" prefix="s" %>
<%
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>
<title>修改影片</title>
</head>
<body>
<s:form action="/film/updateFilm" method="post" enctype="multipart/form-data">
<s:hidden name="id" />
影片名稱:<s:textfield name="fname" /><br />
<%-- 處理原有圖片 --%>
<s:if test='imgurl != null and imgurl != ""'>
<%-- 保存原有圖片的信息在修改時提交 --%>
<s:hidden name="imgurl"></s:hidden>
<%-- 顯示原有圖片,onerror屬性:在打不開圖片時顯示提示圖片 --%>
<img src="<s:property value="imgurl" />" width="92" height="130"
onerror="javascript:this.src='<%=basePath %>/images/error.gif'" /><br />
</s:if>
<%--文件選擇框 --%>
影片海報:<s:file id="imgPhoto" name="imgPhoto"/><br />
<s:submit value=" 修改 "></s:submit>
</s:form>
</body>
</html>
7、struts.xml中添加、修改影片Action的配置中加入的Struts2的文件處理攔截器,配置如下:
<?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> <constant name="struts.enable.DynamicMethodInvocation" value="true" /> <constant name="struts.devMode" value="true" /> <constant name="struts.i18n.encoding" value="UTF-8" /> <constant name="struts.objectFactory" value="spring" /> <constant name="struts.objectFactory.spring.autoWire" value="type" /> <constant name="struts.ui.theme" value="simple"></constant> <package name="film" namespace="/film" extends="struts-default"> <!-- 獲取所有影片 --> <action name="findFilm" class="filmAction" method="findFilm"> <result name="success">/manager/films.jsp</result> </action> <!-- 添加影片 --> <action name="insertFilm" class="filmAction" method="insertFilm"> <!-- 默認攔截器 --> <interceptor-ref name="defaultStack" /> <!-- 文件上傳攔截器 --> <interceptor-ref name="fileUploadStack"> <!-- 配置允許上傳的文件大小,單位字節(默認2M) --> <param name="maximumSize">10000000</param> <param name="allowedTypes"> image/bmp,image/png,image/gif,image/jpeg </param> </interceptor-ref> <result name="success" type="redirectAction">findFilm</result> </action> <!-- 獲取影片詳情 --> <action name="detailFilm" class="filmAction" method="detailFilm"> <result name="success">/manager/updateFilm.jsp</result> </action> <!-- 修改影片 --> <action name="updateFilm" class="filmAction" method="updateFilm"> <!-- 默認攔截器 --> <interceptor-ref name="defaultStack" /> <!-- 文件上傳攔截器 --> <interceptor-ref name="fileUploadStack"> <!-- 配置允許上傳的文件大小,單位字節(默認2M) --> <param name="maximumSize">10000000</param> <param name="allowedTypes"> image/bmp,image/png,image/gif,image/jpeg </param> </interceptor-ref> <result name="success" type="redirectAction">findFilm</result> </action> <!-- 刪除影片 --> <action name="deleteFilm" class="filmAction" method="deleteFilm"> <result name="success" type="redirectAction">findFilm</result> </action> </package> </struts>
fileUploadStack攔截器的參數allowedTypes爲限制上傳文件的類型,文件類型與限制方式的對應關係如下:
文件類型 限制方式
==================================
.a application/octet-stream
.ai application/postscript
.aif audio/x-aiff
.aifc audio/x-aiff
.aiff audio/x-aiff
.au audio/basic
.avi video/x-msvideo
.bat text/plain
.bcpio application/x-bcpio
.bin application/octet-stream
.bmp image/x-ms-bmp
.c text/plain
.cdf application/x-cdf
.cdf application/x-netcdf
.cpio application/x-cpio
.csh application/x-csh
.css text/css
.dll application/octet-stream
.doc application/msword
.dot application/msword
.dvi application/x-dvi
.eml message/rfc822
.eps application/postscript
.etx text/x-setext
.exe application/octet-stream
.gif image/gif
.gtar application/x-gtar
.h text/plain
.hdf application/x-hdf
.htm text/html
.html text/html
.ief image/ief
.jpe image/jpeg
.jpeg image/jpeg
.jpg image/jpeg
.js application/x-javascript
.ksh text/plain
.latex application/x-latex
.m1v video/mpeg
.man application/x-troff-man
.me application/x-troff-me
.mht message/rfc822
.mhtml message/rfc822
.mif application/x-mif
.mov video/quicktime
.movie video/x-sgi-movie
.mp2 audio/mpeg
.mp3 audio/mpeg
.mpa video/mpeg
.mpe video/mpeg
.mpeg video/mpeg
.mpg video/mpeg
.ms application/x-troff-ms
.nc application/x-netcdf
.nws message/rfc822
.o application/octet-stream
.obj application/octet-stream
.oda application/oda
.p12 application/x-pkcs12
.p7c application/pkcs7-mime
.pbm image/x-portable-bitmap
.pdf application/pdf
.pfx application/x-pkcs12
.pgm image/x-portable-graymap
.pl text/plain
.png image/png
.pnm image/x-portable-anymap
.pot application/vnd.ms-powerpoint
.ppa application/vnd.ms-powerpoint
.ppm image/x-portable-pixmap
.pps application/vnd.ms-powerpoint
.ppt application/vnd.ms-powerpoint
.ps application/postscript
.pwz application/vnd.ms-powerpoint
.py text/x-python
.pyc application/x-python-code
.pyo application/x-python-code
.qt video/quicktime
.ra audio/x-pn-realaudio
.ram application/x-pn-realaudio
.ras image/x-cmu-raster
.rdf application/xml
.rgb image/x-rgb
.roff application/x-troff
.rtx text/richtext
.sgm text/x-sgml
.sgml text/x-sgml
.sh application/x-sh
.shar application/x-shar
.snd audio/basic
.so application/octet-stream
.src application/x-wais-source
.sv4cpio application/x-sv4cpio
.sv4crc application/x-sv4crc
.swf application/x-shockwave-flash
.t application/x-troff
.tar application/x-tar
.tcl application/x-tcl
.tex application/x-tex
.texi application/x-texinfo
.texinfo application/x-texinfo
.tif image/tiff
.tiff image/tiff
.tr application/x-troff
.tsv text/tab-separated-values
.txt text/plain
.ustar application/x-ustar
.vcf text/x-vcard
.wav audio/x-wav
.wiz application/msword
.wsdl application/xml
.xbm image/x-xbitmap
.xlb application/vnd.ms-excel
.xls application/excel
.xls application/vnd.ms-excel
.xml text/xml
.xpdl application/xml
.xpm image/x-xpixmap
.xsl application/xml
.xwd image/x-xwindowdump
.zip application/zip
8、在FilmAction中加入一組與文件上傳相關的屬性,加入uploadFile方法,在添加、修改操作前調用uploadFile方法處理圖片,代碼如下:
package com.xxx.web.struts.action;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Random;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;
import org.springframework.beans.factory.annotation.Autowired;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.xxx.pojo.Film;
import com.xxx.service.FilmService;
@SuppressWarnings("serial")
public class FilmAction extends ActionSupport implements ModelDriven<Film> {
//業務邏輯對象
@Autowired
private FilmService filmService;
//封裝查詢結果
private List<Film> filmList;
//封裝頁面提交的表單數據
private Film film = new Film();
//圖片服務器url
public static final String IMAGE_SERVER_URL = "http://localhost:8080/mysit";
/* 文件上傳相關屬性 */
private File imgPhoto;// 對應頁面的<s:file id="imgPhoto" name="imgPhoto"/>
private String contentType;// 上傳文件的MIME類型,由struts設置
private String fileName;// 上傳文件的文件名(該文件名不包括文件的路徑),由struts設置
/* 文件上傳相關屬性的getter/setter */
public File getImgPhoto() {
return imgPhoto;
}
public void setImgPhoto(File imgPhoto) {
this.imgPhoto = imgPhoto;
}
/*
* 注意:contentType與fileName的getter/setter,
* 名稱前需要加ImgPhoto,這樣設置struts才能識別
*/
public String getImgPhotoContentType() {
return contentType;
}
public void setImgPhotoContentType(String contentType) {
this.contentType = contentType;
}
public String getImgPhotoFileName() {
return fileName;
}
public void setImgPhotoFileName(String fileName) {
this.fileName = fileName;
}
/**
* 處理上傳的文件
*/
private void uploadFile(){
//判斷文件是否上傳
if (this.imgPhoto == null || this.fileName == null
|| this.fileName.equals("")) {//沒有上傳文件
return;
}
/*生成一個隨機文件名*/
// 生成隨機數
Random rand = new Random();
int random = rand.nextInt();
random = random > 0 ? random : (-1) * random;// 隨機負數轉爲正數
// 獲取當前時間
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat(
"yyyyMMddHHmmss");
//將當前時間轉換爲yyyyMMddHHmmss格式
String currentTime = sdf.format(date);
//設置文件名(新文件名 = 當前時間 + 隨機數 + 上傳文件的後綴名)
String imageFileName = currentTime + random +
fileName.substring(fileName.lastIndexOf("."));
/*設置上傳文件的保存路徑*/
//獲取web服務器工作路徑
String realPath =
ServletActionContext.getServletContext().getRealPath("/images");
//文件的存放位置 = web服務器中項目的images路徑 + 新文件名
File destinationFile = new File(realPath + "/" + imageFileName);
//將上傳文件拷貝到web服務器
try {
FileUtils.copyFile(this.imgPhoto, destinationFile);
} catch (IOException e) {
e.printStackTrace();
}
/*
將上傳圖片的完整url設置給film對象,在後續的添加操作中保存到數據庫,
設置完整url的目的是便於以後使用單獨的圖片服務器保存圖片,前臺頁面
可直接讀取這個url呈現圖片,圖片服務器的url可設置到配置文件中,這裏
用一個靜態變量來保存
*/
this.film.setImgurl(IMAGE_SERVER_URL + "/images/" + imageFileName);
}
/**
* 獲取所有的電影
* @return
* @throws Exception
*/
public String findFilm() throws Exception {
this.filmList = this.filmService.getAllFilm();
return SUCCESS;
}
/**
* 根據影片ID獲取影片信息
* @return
* @throws Exception
*/
public String detailFilm() throws Exception {
int id = film.getId().intValue();
Film film = this.filmService.getFilmById(id);
this.film.setFname(film.getFname());
this.film.setImgurl(film.getImgurl());
return SUCCESS;
}
/**
* 添加影片
* @return
* @throws Exception
*/
public String insertFilm() throws Exception {
//處理上傳圖片
this.uploadFile();
this.filmService.insertFilm(film);
return SUCCESS;
}
/**
* 修改影片
* @return
* @throws Exception
*/
public String updateFilm() throws Exception {
//處理上傳圖片
this.uploadFile();
this.filmService.updateFilm(film);
return SUCCESS;
}
/**
* 刪除影片
* @return
* @throws Exception
*/
public String deleteFilm() throws Exception {
int id = film.getId().intValue();
this.filmService.deleteFilm(id);
return SUCCESS;
}
public Film getModel() {
return film;
}
public List<Film> getFilmList() {
return filmList;
}
public void setFilmList(List<Film> filmList) {
this.filmList = filmList;
}
}
9、在films.jsp頁面的影片列表中呈現出圖片,如下:
影片列表頁面效果圖:
films.jsp代碼:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8" %>
<%@taglib uri="/struts-tags" prefix="s" %>
<%
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>
<title>信息操作</title>
</head>
<body>
<s:form action="/film/findFilm" method="post">
<s:submit value=" 獲取所有影片信息 "></s:submit>
</s:form>
<a href="<%=basePath %>manager/insertFilm.jsp">添加影片信息</a><br />
<s:if test="filmList != null">
<table border="1" width="40%">
<tr>
<th>序號</th><th>海報</th><th>影片名</th><th>操作</th>
</tr>
<%-- 遍歷影片信息 --%>
<s:iterator var="film" value="filmList" status="st">
<tr>
<td><s:property value="#st.index+1" /></td>
<td>
<%-- 顯示海報圖片,onerror屬性:在打不開圖片時顯示提示圖片 --%>
<img src="<s:property value="imgurl" />" width="92" height="130"
onerror="javascript:this.src='<%=basePath %>/images/error.gif'" /><br />
</td>
<td><s:property value="fname" /></td>
<td>
<s:url id="detailUrl" value="/film/detailFilm">
<s:param name="id" value="%{id}"/>
</s:url>
<s:a href="%{detailUrl}">[修改]</s:a>
<s:url id="deleteUrl" value="/film/deleteFilm">
<s:param name="id" value="%{id}"/>
</s:url>
<s:a href="%{deleteUrl}">[刪除]</s:a>
</td>
</tr>
</s:iterator>
</table>
</s:if>
</body>
</html>