使用过滤器移除Word文件水印

还是移除Word水印的问题,这次需要在应用系统上实现用户请求Word文件时,自动把Word的水印移除。这次的重点不是如何移除Word水印的问题,而是如何实现在response发送给客户端之前对数据流进行修改。实现的方式是实现自己的HttpServletResponseWrapper类并进行相应的修改操作。

直接上代码:

 

/**
 * @CopyRright (c)2011: BrokenStone
 * @Project: WordWatermark
 * @File:    RemoveWordWatermarkFilter.java
 * @JDK version used:  JDK1.6
 * @<br/>
 * @Author: BrokenStone
 * @Blog:   http://sheng.javaeye.com)
 * @Email:  wdmsyf@yahoo.com
 * @since:  2012-1-13
 * @Ver:    1.0
 */
package com.iteye.sheng.utils.office.tools;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

/**
 * @author ShengYoufu
 *
 */
public class RemoveWordWatermarkFilter implements Filter {
	private static final Logger log = Logger.getLogger(RemoveWordWatermarkFilter.class);

	//需要过过滤的请求服务器IP,因为mastudio没有较好的办法让应用系统知道是mastudio发起的请求,所以就先按IP来区分
	//如果有更好的办法,建议改成更好的办法来处理
	private static String[] filterSourceIPs = {"145.24.16.134"};
	
	/* (non-Javadoc)
	 * @see javax.servlet.Filter#destroy()
	 */
	public void destroy() {
		//
	}

	/* (non-Javadoc)
	 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
	 */
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
		log.debug("Enter into doFilter...");
		if(resp instanceof HttpServletResponse){
			String requestIP = getRealRemoteAddress((HttpServletRequest)req, (HttpServletResponse)resp);
			log.debug("Remote address(IP):" + requestIP);
			if(needProcess(requestIP)){
				log.debug("Begin process...");
				RemoveWordWatermarkResponse response = new RemoveWordWatermarkResponse((HttpServletResponse)resp);
				chain.doFilter(req, response);
				log.debug("End process.");
				return;
			}
		}
		chain.doFilter(req, resp);
	}

	/* (non-Javadoc)
	 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
	 */
	public void init(FilterConfig config) throws ServletException {
		String sourceIP = config.getInitParameter("filterSourceIP");
		String[] temp = sourceIP.split(";");
		if(temp!=null && temp.length>0)
			filterSourceIPs = temp;
	}
	
	protected boolean needProcess(String requestIP){
		for(int ii=0; ii<filterSourceIPs.length; ii++){
			if(filterSourceIPs[ii].equals(requestIP)) return true;
		}
		return false;
	}
	
	protected String getRealRemoteAddress(HttpServletRequest req, HttpServletResponse resp){
		if(req == null){
			return null;
		}
		// 如果有apache
		String ip = req.getHeader("X-Forwarded-For");
		
		if (ip == null || ip.length() == 0) {
			// 如果有weblogic配置
			ip = req.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0) {
			ip = req.getRemoteAddr();
		}
		return ip;
	}

}

 

/**
 * @CopyRright (c)2011: BrokenStone
 * @Project: WordWatermark
 * @File: RemoveWordWatermarkResponse.java
 * @JDK version used: JDK1.6 @<br/>
 * @Author: BrokenStone
 * @Blog: http://sheng.javaeye.com)
 * @Email: wdmsyf@yahoo.com
 * @since: 2012-1-13
 * @Ver: 1.0
 */
package com.iteye.sheng.utils.office.tools;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

import org.apache.log4j.Logger;

/**
 * @author ShengYoufu
 * 
 */
public class RemoveWordWatermarkResponse extends HttpServletResponseWrapper {
	private static final Logger log = Logger.getLogger(RemoveWordWatermarkResponse.class);
	
	protected ServletOutputStream stream = null;
	protected PrintWriter writer = null;
	public HttpServletResponse origResponse = null;
	protected static Pattern pattern = Pattern.compile("attachment;filename=(.*)(\\.doc)$");  //判断是否word文件正则表达式
	protected Map headerMap = new HashMap();
	protected int contentLength = 0;

	/**
	 * 
	 * @param response
	 */
	public RemoveWordWatermarkResponse(HttpServletResponse response) {
		super(response);
		origResponse = response;
	}

	public void addHeader(String name, String value){
		super.addHeader(name, value);
		this.headerMap.put(name, value);
	}

	public Map getAllHeaders(){
		return this.headerMap;
	}
	
	public String getHeader(String name){
		return (String)this.headerMap.get(name);
	}
	
	/**
	 * 重载setContentLength是为了能取得原来写入response的数据长度
	 */
	public void setContentLength(int contentLength){
		super.setContentLength(contentLength);
		this.contentLength = contentLength;
	}

	public int getContentLength(){
		return this.contentLength;
	}
	
	/**
	 * 判断是否是Word文档
	 * @return
	 */
	public boolean isWordDocument(){
		Iterator it = this.headerMap.keySet().iterator();
		while(it.hasNext()){
			String name = (String)it.next();
			if("Content-Disposition".equals(name)){
				String val = (String)this.headerMap.get(name);
				Matcher matcher = pattern.matcher(val);
				if(matcher.find()) return true;
			}
		}
		return false;
	}
	
	/**
	 * 创建自定义OutputStream
	 * @return
	 * @throws IOException
	 */
	public ServletOutputStream createOutputStream() throws IOException {
		//只处理Word文件
		if(isWordDocument()){
			log.debug("Create RemoveWordWatermarkFilterServletOutputStream...");
			return (new RemoveWordWatermarkFilterServletOutputStream(this));
		} else
			return origResponse.getOutputStream();
	}

	/**
	 * 返回自定义的OutputStream(自动把Word文件的水印删除)
	 */
	public ServletOutputStream getOutputStream() throws IOException {
		if (writer != null) {
			throw new IllegalStateException("getWriter() has already been " + "called for this response");
		}
		if (stream == null) {
			stream = createOutputStream();
		}
		return stream;
	}

	/**
	 * 返回包装自定义OutputStream的Writer(自动把水印删除)
	 */
	public PrintWriter getWriter() throws IOException {
		if (writer != null) {
			return writer;
		}
		if (stream != null) {
			throw new IllegalStateException("getOutputStream() has already " + "been called for this response");
		}
		stream = createOutputStream();
		writer = new PrintWriter(stream);
		return writer;
	}
	
	
}

 

 

/**
 * @CopyRright (c)2011: BrokenStone
 * @Project: WordWatermark
 * @File: RemoveWordWatermarkFilterServletOutputStream.java
 * @JDK version used: JDK1.6 @<br/>
 * @Author: BrokenStone
 * @Blog: http://sheng.javaeye.com)
 * @Email: wdmsyf@yahoo.com
 * @since: 2012-1-13
 * @Ver: 1.0
 */
package com.iteye.sheng.utils.office.tools;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletOutputStream;

import org.apache.log4j.Logger;

import com.aspose.words.Document;

/**
 * @author ShengYoufu
 * 
 */
public class RemoveWordWatermarkFilterServletOutputStream extends ServletOutputStream {
	private static final Logger log = Logger.getLogger(RemoveWordWatermarkFilterServletOutputStream.class);
	
	private OutputStream _out;
	private RemoveWordWatermarkResponse _response = null;
	private ByteArrayOutputStream _buffer;
	private boolean closed = false;
	private int ContentLength = 0;
	private int _bufferSize = 0;

	public RemoveWordWatermarkFilterServletOutputStream( RemoveWordWatermarkResponse resp ) throws IOException{
		_buffer = new ByteArrayOutputStream();
//		_out = resp.getOutputStream();
		_out = resp.getResponse().getOutputStream();
		_response = resp;
	}
	protected RemoveWordWatermarkFilterServletOutputStream( OutputStream realStream ) throws IOException{
		_buffer = new ByteArrayOutputStream();
		_out = realStream;
	}

	public void close() throws IOException {
		if (closed) {
			throw new IOException("This output stream has already been closed");
		}

		//移除水印
		try{
			removeWatermark();
		}catch(Exception ex){
			throw new IOException("移除Word水印失败: "+ ex.getMessage());
		}

		_out.flush();
		_out.close();
		closed = true;
	}

	public void flush() throws IOException {
		if (closed) {
			throw new IOException("Cannot flush a closed output stream");
		}

		//移除水印
		try{
			removeWatermark();
		}catch(Exception ex){
			throw new IOException("移除Word水印失败: "+ ex.getMessage());
		}
		_out.flush();
	}

	public void write(int b) throws IOException {
		if (closed) {
			throw new IOException("Cannot write to a closed output stream");
		}
		//对于单个字节,不需要执行移除水印操作
//		_buffer.write((byte) b);
		_out.write(b);
	}

	public void write(byte b[]) throws IOException {
		write(b, 0, b.length);
	}

	public void write(byte b[], int off, int len) throws IOException {
		if (closed) {
			throw new IOException("Cannot write to a closed output stream");
		}

//		log.debug("Enter into write...");

		_buffer.write(b, off, len);

		_bufferSize += len;
		
		//当写入的数据小于1024(缓冲区大小)时,则认为写入数据已经结束,可以进行移除水印操作了。
		//当总的数据长度已经达到原Response中设定值,则认为写入数据已经结束,可以进行移除水印操作了。
		if(len<1024 || _bufferSize >= _response.getContentLength()){	
			try {
				removeWatermark();
			} catch (Exception ex) {
				log.error("移除水印失败。",ex);
				throw new IOException("移除水印失败。");
			}
		}
	}

	/**
	 * 移除水印操作
	 * @throws Exception
	 */
	public void removeWatermark() throws Exception {
		log.debug("Enter into removeWatermark...");
		
		//载入Aspose.Words组件的许可证
		WordWatermarkUtil.loadLicense();

		ByteArrayInputStream bais = null;
		byte[] buff = null;
		byte[] buf = new byte[1024];
		int len = 0;

		long beginTime = System.currentTimeMillis();  

		//记下新的ContentLength
		this.setContentLength(_buffer.size());
		if(_response!=null){
			_response.setContentLength(_buffer.size());
		}

		try{
			try{
				_buffer.flush();
				buff = _buffer.toByteArray();
				bais = new ByteArrayInputStream(_buffer.toByteArray());
				_buffer.close();
			}catch(IOException ex){
				throw new Exception("缓冲字节流flush失败。", ex);
			}
			
			try{
				Document doc = new Document(bais);
				bais.close();
				WordWatermarkUtil.removeWatermark(doc);
				_buffer = new ByteArrayOutputStream();
				doc.save(_buffer, null);
				if(_response!=null){
					_response.setContentLength(_buffer.size());
				}
				bais = new ByteArrayInputStream(_buffer.toByteArray());
				while( (len = bais.read(buf))>0){
					_out.write(buf, 0, len);
				}
				log.debug("Remove watermark from doc succeed.");
			}catch(Exception ex){
				log.error("从Word文件中移除水印失败,直接用原文件返回.", ex);

				bais = new ByteArrayInputStream(buff);

				while( (len = bais.read(buf)) > 0){
					_out.write(buf, 0, len);
				}
			}
		}finally{
			try {
				_buffer.close();
			} catch (IOException ex) {
				log.warn("关闭临时缓冲字节流失败.", ex);
			}
			if(bais!=null){
				bais.close();
			}
			bais = null;
			
			long endTime = System.currentTimeMillis();
			log.debug("移除Word文档水印耗时:"+String.valueOf( endTime - beginTime) + " ms");
		}
	}
	
	/**
	 * 
	 * @param args
	 */
	public static void main(String[] args){
		FileInputStream fis = null;
		FileOutputStream fos = null;

		//载入Aspose.Words的许可证
		WordWatermarkUtil.loadLicense();

		try {
			fis = new FileInputStream("C:\\with_watermark.doc");
			fos = new FileOutputStream("C:\\test1.doc");
			RemoveWordWatermarkFilterServletOutputStream os = new RemoveWordWatermarkFilterServletOutputStream(fos);
			byte[] buf = new byte[1024];
			int len = 0;
			while( (len = fis.read(buf))>0){
				os.write(buf, 0, len);
			}
			os.flush();
			os.close();
			fos.flush();
			fos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(fis!=null){
				try {
					fis.close();
				} catch (IOException ex) {
					ex.printStackTrace();
				}
			}
			fis = null;

			if(fos!=null){
				try {
					fos.flush();
				} catch (IOException ex){
					ex.printStackTrace();
				}
				try {
					fos.close();
				} catch (IOException ex) {
					ex.printStackTrace();
				}
			}
			fos = null;
		}
	}

	public int getContentLength() {
		return ContentLength;
	}

	public void setContentLength(int contentLength) {
		ContentLength = contentLength;
	}
}

 

 

/**
 * @CopyRright (c)2011: BrokenStone
 * @Project: WordWatermark
 * @File:    WordWatermarkUtil.java
 * @JDK version used:  JDK1.6
 * @<br/>
 * @Author: BrokenStone
 * @Blog:   http://sheng.javaeye.com)
 * @Email:  wdmsyf@yahoo.com
 * @since:  2012-1-13
 * @Ver:    1.0
 */
package com.iteye.sheng.utils.office.tools;

import java.awt.Color;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import com.aspose.words.Document;
import com.aspose.words.HeaderFooter;
import com.aspose.words.HeaderFooterType;
import com.aspose.words.HorizontalAlignment;
import com.aspose.words.License;
import com.aspose.words.Paragraph;
import com.aspose.words.RelativeHorizontalPosition;
import com.aspose.words.RelativeVerticalPosition;
import com.aspose.words.Section;
import com.aspose.words.SectionCollection;
import com.aspose.words.Shape;
import com.aspose.words.ShapeType;
import com.aspose.words.VerticalAlignment;
import com.aspose.words.WrapType;

/**
 * @author ShengYoufu
 *
 */
public class WordWatermarkUtil {


	/**
	 * 
	 * Inserts a watermark into a document.
	 * 
	 * @param doc The input document.
	 * @param watermarkText Text of the watermark.
	 * 
	 */
	public static void insertWatermarkText(Document doc, String watermarkText) throws Exception {
		// Create a watermark shape. This will be a WordArt shape.
		// You are free to try other shape types as watermarks.
		Shape watermark = new Shape(doc, ShapeType.TEXT_PLAIN_TEXT);
		// Set up the text of the watermark.
		watermark.getTextPath().setText(watermarkText);
		watermark.getTextPath().setFontFamily("Arial");
		watermark.setWidth(500);
		watermark.setHeight(100);
		// Text will be directed from the bottom-left to the top-right corner.
		watermark.setRotation(-40);
		// Remove the following two lines if you need a solid black text.
		watermark.getFill().setColor(Color.GRAY); // Try LightGray to get more Word-style watermark
		watermark.setStrokeColor(Color.GRAY); // Try LightGray to get more Word-style watermark
		// Place the watermark in the page center.
		watermark.setRelativeHorizontalPosition(RelativeHorizontalPosition.PAGE);
		watermark.setRelativeVerticalPosition(RelativeVerticalPosition.PAGE);
		watermark.setWrapType(WrapType.NONE);
		watermark.setVerticalAlignment(VerticalAlignment.CENTER);
		watermark.setHorizontalAlignment(HorizontalAlignment.CENTER);
		// Create a new paragraph and append the watermark to this paragraph.
		Paragraph watermarkPara = new Paragraph(doc);
		watermarkPara.appendChild(watermark);
		
		// Insert the watermark into all headers of each document section.
		SectionCollection sects = doc.getSections();
		Iterator it = sects.iterator();
		while(it.hasNext()){
			Section sect = (Section)it.next();
			// There could be up to three different headers in each section, since we want
			// the watermark to appear on all pages, insert into all headers.
			insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_PRIMARY);
			insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_FIRST);
			insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_EVEN);
		}
	}

	/**
	 * 插入水印
	 * @param watermarkPara
	 * @param sect
	 * @param headerType
	 * @throws Exception
	 */
	public static void insertWatermarkIntoHeader(Paragraph watermarkPara, Section sect, int headerType) throws Exception {
		HeaderFooter header = sect.getHeadersFooters().getByHeaderFooterType(headerType);
		if (header == null) {
			// There is no header of the specified type in the current section, create it.
			header = new HeaderFooter(sect.getDocument(), headerType);
			sect.getHeadersFooters().add(header);
		}

		// Insert a clone of the watermark into the header.
		header.appendChild(watermarkPara.deepClone(true));
	}

	/**
	 * 移除全部水印
	 * @param inStream
	 * @throws Exception
	 */
	public static void removeWatermark(InputStream inStream) throws Exception {
		Document doc = new Document(inStream);
		removeWatermark(doc);
	}
	
	/**
	 * 移除全部水印
	 * @param doc
	 * @throws Exception
	 */
	public static void removeWatermark(Document doc) throws Exception {
		SectionCollection sects = doc.getSections();
		Iterator it = sects.iterator();
		while(it.hasNext()){
			Section sect = (Section)it.next();
			// There could be up to three different headers in each section, since we want
			// the watermark to appear on all pages, insert into all headers.
			removeWatermarkFromHeader(sect, HeaderFooterType.HEADER_PRIMARY);
			removeWatermarkFromHeader(sect, HeaderFooterType.HEADER_FIRST);
			removeWatermarkFromHeader(sect, HeaderFooterType.HEADER_EVEN);
		}
	}
	
	/**
	 * 移除指定Section的水印
	 * @param sect
	 * @param headerType
	 * @throws Exception
	 */
	public static void removeWatermarkFromHeader(Section sect, int headerType) throws Exception {
		HeaderFooter header = sect.getHeadersFooters().getByHeaderFooterType(headerType);
		if (header != null) {
			header.removeAllChildren();
		}
	}
	
	/**
	 * 从Classpath(jar文件中)中读取License
	 */
	public static void loadLicense() {
	  //返回读取指定资源的输入流
	  License license = new License();
	  InputStream is = null;
	  try {
	    is = WordWatermarkUtil.class.getResourceAsStream("/resources/aspose.word.license.xml");
	    if(is==null) 
	      throw new RuntimeException("Cannot find licenses file. Please contact wdmsyf@yahoo.com or visit http://sheng.javaeye.com for get more information.");
	    license.setLicense(is);
	  } catch (Exception ex) {
	    ex.printStackTrace();
	  }finally{
	    if(is!=null){
	      try{ is.close(); }catch(IOException ex){ };
	      is = null;
	    }
	  }
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		loadLicense();
		Document doc = new Document("c:/with_watermark.doc");
		removeWatermark(doc);
		doc.save("c:/without_watermark.doc");
	}

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值