资源描述
从MS word文档获取图片
2010-07-18 19:47
本文包括如何用java从WORD文档获取图片和其他二进制嵌入式对象的演示
Microsoft 从office 2003开始支持将文档保存为XML. 图片则以二进制形式嵌入在XML文档中, 它使用BASE 64 编码. MS Word 使用 w:binData 标签存储嵌入式二进制数据, 并使用伪协议wordml创建一个name属性. URI可以使一个带有文件类型扩展名的名字. 例如
<w:binData w:name="wordml://01000002.gif">
<w:binData w:name="wordml://03000001.png">
标签的内容是BASE64 编码的二进制数据. 没有其他标记来说明这个了, 就是嵌规则哈.
使用一个 SAX parser 就可以很方便地把图片数据解析出来. 看看下面的例子吧, 可以把二进制数据包括所有图片从WORD文档解析出来, 并存到文件里.
运行方法: java com.doylecentral.word.FileTester wordFile.xml outputDirectory
其中 FileTester 这个类用来提供一个简单的例子, 说明如何使用这些类, 看看它就明白怎么用了.
写到文件系统里这一步是随意的, 也可以随时改主意, 送到数据库里去.
设计的思路如下:
public class ImageExtractor {
CharArrayWriter text = new CharArrayWriter();
Map dataMap = new HashMap();
int foundImages;
public ImageExtractor() {
//C
}
/**
* InputStream is closed internally.
* @param is
* @throws IOException
*/
public ImageExtractor(InputStream is) throws IOException {
parseXmlFile(is, new ImageParseHandler() , false);
is.close();
}
/**
* Refuse to Validate against dtd.
* @param is
* @param handler
* @param validating
*/
private void parseXmlFile(InputStream is, DefaultHandler handler,
boolean validating)
{
try
{
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating(validating);
factory.newSAXParser().parse(is , handler);
} catch (SAXException e)
{
// A parsing error occurred; the xml input is not valid
} catch (ParserConfigurationException e)
{
//
} catch (IOException e)
{
//
}
}
private class ImageParseHandler extends DefaultHandler {
private boolean inImage = false;
private StringBuffer encodedDataSb = null;
private String imageName;
Locator locator;
public void setDocumentLocator(Locator locator)
{
this.locator = locator;
}
public void characters(char[] chars, int start, int len)
throws SAXException
{
if (inImage)
{
encodedDataSb.append(new String(chars, start, len));
}
}
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException
{
text.reset();
if (qName.equals("w:binData"))
{
imageName = attributes.getValue("w:name");
if (imageName.endsWith(".png") || imageName.endsWith(".jpg"))
{
encodedDataSb = new StringBuffer();
inImage = true;
} else
{
inImage = false;
}
foundImages++;
}
}
public void endElement(String uri, String localName, String qName)
throws SAXException
{
if (qName.equals("w:binData") && inImage)
{
ByteArrayInputStream is = new ByteArrayInputStream(encodedDataSb.toString().getBytes());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageDecoder id = new ImageDecoder();
id.decodeImage(is, baos);
dataMap.put(imageName, baos.toByteArray());
try
{
is.close();
baos.close();
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
inImage = false;
}
}
}
public int getFoundImages()
{
return foundImages;
}
public Map getDataMap()
{
return dataMap;
}
}
下面的代码用来处理Base64解码. 当然也可以改用 Jakarta Commons Codec package 来做. classpath里别忘了添加GCJ.
public class ImageDecoder {
public void decodeImage(InputStream is, OutputStream os)
{
BASE64Decoder decoder = new BASE64Decoder();
try
{
decoder.decodeBuffer(is, os);
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
展开阅读全文