存档

文章标签 ‘flashfileupload’

Struts2+FlashFileUpload文件上传并生成缩略图和添加水印

2009年11月6日 IT北瓜 21 条评论

      以前用过SWFUpload,功能确实很强大。javaeye上有人发布了这样一篇文章step-by-step多文件WEB批量上传(swfupload)的完美解决方案有兴趣的朋友可以看一下。Leeo觉得SWFUpload稍微不足的就是界面的定制,总感觉自己定制出来的界面有点难登大雅之堂。下面Leeo为大家介绍一下,如何使用FlashFileUpload这个Flash组件来实现多文件上传,并且通过java程序自动生成缩略图和添加水印,FlashFileUpload定制出来的界面还是挺漂亮的(PS:这个界面是Leeo从UUShare上弄下来的,^_^),先来Show一张效果图:

      从上面的图片从可以看出中间有个水印(PS:本博客的Logo),这并不是用Photoshop之类的软件弄上去的,而是通过下面将要讲到的java程序自动添加的,效果很不错,(*^__^*) 嘻嘻……好,正式开始吧…

      第一步:当然是获取flashfileupload.swf这个Flash组件啦,大家可以从这里下载,或者其他什么途径得到都行

      第二步:编写上传页面的代码如下:

 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
  String uploadType = (String)request.getParameter("uploadType");
  Long filmid = Long.parseLong((String)request.getParameter("filmid"));
  //out.print(uploadType);
  //out.print(filmid);
%>
<object id="fileUpload"
    codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab#version=10,0,22,87"
    height="310" width="500" align="middle"
    classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000">
    <param name="_cx" value="13229" />
    <param name="_cy" value="8202" />
    <%
        if("Video".equals(uploadType)){
    %>
    <param name="flashvars" value="fileTypeDescription=允许视频格式&fileTypes=*.asx;*.asf;*.mpg;*.wmv;*.3gp;*.mp4;*.mov;*.avi;*.flv;*.wmv9;*.rm;*.rmvb&completeFunction=UploadComplete()&fileSizeLimit=3000000&totalUploadSize=10240000&accounttype=0&uploadPage=flashupload!Upload.action;jsessionid=${session.id}?uploadType=<%=uploadType %>-<%=filmid %>" />
    <%
        }else{
    %>
    <param name="flashvars" value="fileTypeDescription=JPG格式图片&fileTypes=*.jpg;*.jpeg&completeFunction=UploadComplete()&fileSizeLimit=3000000&totalUploadSize=10240000&accounttype=0&uploadPage=flashupload!Upload.action;jsessionid=${session.id}?uploadType=<%=uploadType %>-<%=filmid %>" />
    <%
        }
    %>
    <param name="movie" value="flashfileupload.swf?ver=20090520" />
    <param name="src" value="flashfileupload.swf?ver=20090520" />
    <param name="wmode" value="transparent" />
    <param name="play" value="0" />
    <param name="loop" value="-1" />
    <param name="quality" value="high" />
    <param name="salign" value="lt" />
    <param name="menu" value="-1" />
    <param name="base" value="" />
    <param name="allowscriptaccess" value="sameDomain" />
    <param name="scale" value="noscale" />
    <param name="devicefont" value="0" />
    <param name="embedmovie" value="0" />
    <param name="bgcolor" value="" />
    <param name="swremote" value="" />
    <param name="moviedata" value="" />
    <param name="seamlesstabbing" value="1" />
    <param name="profile" value="0" />
    <param name="profileaddress" value="" />
    <param name="profileport" value="0" />
    <param name="allownetworking" value="all" />
    <param name="allowfullscreen" value="true" />
    <%
        if("Video".equals(uploadType)){
    %>
    <embed src="flashfileupload.swf?ver=20090520"
        flashvars="fileTypeDescription=允许视频格式&fileTypes=*.asx;*.asf;*.mpg;*.wmv;*.3gp;*.mp4;*.mov;*.avi;*.flv;*.wmv9;*.rm;*.rmvb&completeFunction=UploadComplete()&fileSizeLimit=3000000&totalUploadSize=10240000&accounttype=0&uploadPage=flashupload!Upload.action;jsessionid=${session.id}?uploadType=<%=uploadType %>-<%=filmid %>"
        quality="high"
        wmode="transparent"
        width="500"
        height="310"
        name="fileUpload"
        align="middle"
        allowscriptaccess="samedomain"
        type="application/x-shockwave-flash"
        pluginspage="http://www.macromedia.com/go/getflashplayer">
    </embed>
    <%
        }else{
    %>
    <embed src="flashfileupload.swf?ver=20090520"
        flashvars="fileTypeDescription=JPG格式图片&fileTypes=*.jpg;*.jpeg&completeFunction=UploadComplete()&fileSizeLimit=3000000&totalUploadSize=10240000&accounttype=0&uploadPage=flashupload!Upload.action;jsessionid=${session.id}?uploadType=<%=uploadType %>-<%=filmid %>"
        quality="high"
        wmode="transparent"
        width="500"
        height="310"
        name="fileUpload"
        align="middle"
        allowscriptaccess="samedomain"
        type="application/x-shockwave-flash"
        pluginspage="http://www.macromedia.com/go/getflashplayer">
    </embed>
    <%
        }
    %>
</object>

说明:其中主要的是flashvars这个参数的设置(PS:Leeo本人对这里的设置也仅仅是略知一二)

fileTypeDescription:允许上传文件的类型描述

fileTypes:允许上传的文件类型

completeFunction:上传完成后调用的js函数

fileSizeLimit:文件大小限制

totalUploadSize:一次性上传文件总大小限制

accounttype:这个没搞清楚怎么用,如果哪位知道的请告知一声,谢谢…

uploadPage:上传文件的请求路径,跟在它后面的是一些用户附加的数据。其中网上有网友说可以;jsessionid=的形式传递session,Leeo没有做测试。?uploadType=是程序中需要的一些附加数据,这里本来需要两个变量的,之所以把它写到一个变量里,然后用“-”隔开两个变量值,就像代码中的<%=uploadType %>-<%=filmid %>,是因为我们知道通常通过url传参是用“&”号隔开的,但这里却不能这么做,因为整个flashvars就是用“&”来隔开不同参数的,如果附加的数据也用“&”隔开就会被截断,得不到我们想要的数据,所以这里用一种比较马虎的解决方法,利用“-”号把不同变量值连接起来,然后在服务器端的java代码中用split("-")再把它们分割开来

    第三步:配置struts.xml文件,如下:

<package name="ajaxfileupload" namespace="/" extends="ajaxfileupload-default">
	<action name="flashupload" class="leeo.action.FlashfileuploadAction">
		<result name="success" type="httpheader">
			<param name="status">200</param>
		</result>
	</action>
</package>

特别说明:这里还用到了ajax-file-upload-plugin-0.4.0.jar(PS:Struts2中用ajxa方式上传文件需要的jar包)

      第四步:编写action类代码,如下:

/** 文件对象 */
private transient File[] Filedata;
/** 文件名 */
/** 文件对象 */
private transient File[] Filedata;
/** 文件名 */
private transient String[] FiledataFileName;
/** 文件内容类型 */
private transient String[] FiledataContentType;

/**
 * 区分是上传海报、剧照、片花
 * **/
private transient String uploadType;

public String Upload() throws Exception {
	System.out.println("FiledataFileName length:" + FiledataFileName.length);
	System.out.println("uploadType:" + uploadType);
	String[] type_filmid = uploadType.split("-");
	System.out.println("filmid:" + type_filmid[1]);

	Film f = filmService.findFilmById(new Long(type_filmid[1]));
	//原文件存放路径  
	String OriginalImageDirectory = ServletActionContext.getServletContext().getRealPath("/UploadFile/" + type_filmid[0] + "/OriginalImage") + System.getProperty("file.separator", "\\");
	for(int i = 0; i < Filedata.length; i ++){
		System.out.println("Filedata["+i+"]:" + Filedata[i]);
		System.out.println("FiledataFileName["+i+"]:" + FiledataFileName[i]);
		System.out.println("FiledataContentType["+i+"]:" + FiledataContentType[i]);

        //在指定目录创建文件
        String newname = FileUpload.getFileName(FiledataFileName[i]);
        File bigFile = new File(OriginalImageDirectory, newname);
        //把要上传的文件copy过去 
        FileUpload.copy(Filedata[i], bigFile);

        if(!"Video".equals(type_filmid[0])){
        	//缩略图存放路径
			String ThumbnailsDirectory = ServletActionContext.getServletContext().getRealPath("/UploadFile/" + type_filmid[0] + "/Thumbnails") + System.getProperty("file.separator", "\\");
			//生成缩略图
			FileUpload.scaleImage(OriginalImageDirectory + newname, ThumbnailsDirectory + newname, 180, 200);
			//设置数据库海报字段路径

			String waterImgFile = ServletActionContext.getServletContext().getRealPath("/UploadFile") + System.getProperty("file.separator", "\\");
	        // 给大图添加文字水印  
	        //FileUpload.watermark(bigFile);  
	        // 给大图添加图片水印,可以是gif或png格式  
	        FileUpload.imageWaterMark(bigFile, waterImgFile);
			File smallFile = new File(ThumbnailsDirectory, newname);
			// 给大图添加文字水印  
	        //FileUpload.watermark(smallFile);  
	        // 给大图添加图片水印,可以是gif或png格式  
	        FileUpload.imageWaterMark(smallFile, waterImgFile);
        }

        /*
         * 操作数据库部分
         * */
        if("Poster".equals(type_filmid[0])){
        	f.setFPoster(newname);
        	filmService.modFilm(f);
        }else if("Still".equals(type_filmid[0])){
        	FilmStill fs = new FilmStill();
        	fs.setFsPath(newname);
        	fs.setFilm(f);
        	filmService.addFilmStill(fs);
        }else if("Video".equals(type_filmid[0])){
        	FilmVideo fv = new FilmVideo();
        	fv.setFvPath(newname);
        	fv.setFilm(f);
        	filmService.addFilmVideo(fv);
        }
	}
	return SUCCESS;
}

public File[] getFiledata() {
	return Filedata;
}

public void setFiledata(File[] filedata) {
	this.Filedata = filedata;
}

public String[] getFiledataFileName() {
	return FiledataFileName;
}

public void setFiledataFileName(String[] filedataFileName) {
	this.FiledataFileName = filedataFileName;
}

public String[] getFiledataContentType() {
	return FiledataContentType;
}

public void setFiledataContentType(String[] filedataContentType) {
	this.FiledataContentType = filedataContentType;
}

public String getUploadType() {
	return uploadType;
}

public void setUploadType(String uploadType) {
	this.uploadType = uploadType;
}

其中,操作数据库部分的代码跟这个例子无关,可以省去。

      第五步:要用到的其他类的代码(PS:这部分代码来自互联网)

      1:FileUpload.java用于生成缩略图、添加水印、生成无重复的文件名

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.imageio.ImageIO;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

public class FileUpload {

	private static final int BUFFER_SIZE = 16 * 1024;
	private static final String WATER_TEXT = "文字水印";
	private static final String WATER_IMG_NAME = "logo.png";

	/*生成无重复文件名*/
    public static String getFileName(String name){

		SimpleDateFormat df =new SimpleDateFormat("yyyyMMddHHmmss");
		Date date = new Date();
		String filename=null;
		if(!"".equals(name) && name != null){
			filename=df.format(date) + RandomNum.random2() + name.substring(name.lastIndexOf("."), name.length());
		}
		System.out.println("filename is:"+filename);
		return filename;
	}

    /*上传文件*/
	public static void copy(File src, File dst) {
        try {
            InputStream in = null;
            OutputStream out = null;
            try {
                in = new BufferedInputStream(new FileInputStream(src), BUFFER_SIZE);
                out = new BufferedOutputStream(new FileOutputStream(dst), BUFFER_SIZE);
                byte[] buffer = new byte[BUFFER_SIZE];
                while (in.read(buffer) > 0) {
                    out.write(buffer);
                }
            } finally {
                if (null != in) {
                    in.close();
                }
                if (null != out) {
                    out.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

	/*生成缩略图*/
	public static String scaleImage(String fromFileStr, String saveToFileStr, int formatWideth, int formatHeight) throws Exception {
		ScaleImage is = new ScaleImage();
		try {
			is.saveImageAsJpg(fromFileStr, saveToFileStr, formatWideth, formatHeight);
        }catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "error";
        }
        return "ok";
	}

	/**
	     * 添加文字水印
	     *
	     * @return
	     * @throws Exception
	     * @throws Exception
	     */
	    public static void watermark(File img) throws Exception {
	        System.out.println("[watermark file name]--" + img.getPath());
	        try {  

	            if (!img.exists()) {
	                throw new IllegalArgumentException("file not found!");
	            }  

	            System.out.println("[watermark][img]--" + img);  

	            // 创建一个FileInputStream对象从源图片获取数据流  
	            FileInputStream sFile = new FileInputStream(img);  

	            // 创建一个Image对象并以源图片数据流填充  
	            Image src = ImageIO.read(sFile);  

	            // 得到源图宽  
	            int width = src.getWidth(null);
	            // 得到源图长  
	            int height = src.getHeight(null);  

	            // 创建一个BufferedImage来作为图像操作容器  
	            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
	            // 创建一个绘图环境来进行绘制图象  
	            Graphics2D g = image.createGraphics();
	            // 将原图像数据流载入这个BufferedImage  
	            System.out.println("width:" + width + " height:" + height);
	            g.drawImage(src, 0, 0, width, height, null);
	            // 设定文本字体  
	            g.setFont(new Font("宋体", Font.BOLD, 28));
	            String rand = WATER_TEXT;
	            // 设定文本颜色  
	            g.setColor(Color.blue);
	            // 设置透明度  
	            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f));
	            // 向BufferedImage写入文本字符,水印在图片上的坐标  
	            g.drawString(rand, width - (width - 20), height - (height - 60));
	            // 使更改生效  
	            g.dispose();
	            // 创建输出文件流  
	            FileOutputStream outi = new FileOutputStream(img);
	            // 创建JPEG编码对象  
	            JPEGImageEncoder encodera = JPEGCodec.createJPEGEncoder(outi);
	            // 对这个BufferedImage (image)进行JPEG编码  
	            encodera.encode(image);
	            // 关闭输出文件流  
	            outi.close();
	            sFile.close();  

	        } catch (IOException e) {
	            e.printStackTrace();
	            throw new Exception(e);
	        }
	    }  

	    /**
	     * 添加图片水印
	     *
	     */
	    public static void imageWaterMark(File imgFile, String waterFilePath) throws Exception {
	        try {
	            // 目标文件  
	            Image src = ImageIO.read(imgFile);
	            int wideth = src.getWidth(null);
	            int height = src.getHeight(null);
	            BufferedImage image = new BufferedImage(wideth, height, BufferedImage.TYPE_INT_RGB);
	            Graphics2D g = image.createGraphics();
	            g.drawImage(src, 0, 0, wideth, height, null);  

	            // 水印文件 路径  
	            String waterImgPath = waterFilePath + WATER_IMG_NAME;
	            System.out.println("waterImgPath--" + waterImgPath);
	            File waterFile = new File(waterImgPath);
	            Image waterImg = ImageIO.read(waterFile);  

	            int w_wideth = waterImg.getWidth(null);
	            int w_height = waterImg.getHeight(null);
	            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f));
	            g.drawImage(waterImg, (wideth - w_wideth) / 2, (height - w_height) / 2, w_wideth, w_height, null);
	            // 水印文件结束  

	            g.dispose();
	            FileOutputStream out = new FileOutputStream(imgFile);
	            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
	            encoder.encode(image);
	            out.close();
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
	    }
}

      2:RandomNum.java用于生成无重复随机数

import java.util.Random;

public class RandomNum {

	public static int[] random1() {
		Random r = new Random();
		int temp1, temp2;
		int send[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 };
		int len = send.length;
		int returnValue[] = new int[22];
		for (int i = 0; i < 22; i++) {
			temp1 = Math.abs(r.nextInt()) % len;
			returnValue[i] = send[temp1];
			temp2 = send[temp1];
			send[temp1] = send[len - 1];
			send[len - 1] = temp2;
			len--;
		}
		return returnValue;
	}
	public static int[] random2() {
		int send[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 };
		int temp1, temp2, temp3;
		Random r = new Random();
		for (int i = 0; i < send.length; i++){// 随机交换send.length次
			temp1 = Math.abs(r.nextInt()) % (send.length - 1); // 随机产生一个位置
			temp2 = Math.abs(r.nextInt()) % (send.length - 1); // 随机产生另一个位置
			if (temp1 != temp2) {
				temp3 = send[temp1];
				send[temp1] = send[temp2];
				send[temp2] = temp3;
			}
		}
		return send;
	}
}

      到此,本应用实例的代码就完成了,赶紧体验一下吧。。。