1、技术目标:
- 为项目"影片管理"加入图片上传功能
- 使用struts2完成图片上传
- 将上传的图片重命名并保存到web服务器
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 11 = 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>