2016-06-09 117 views
1

我知道Mule对使用元素的gzip压缩数据有很大的支持。然而,客户现在想zip压缩,因为该文件已被放置在一个FTP作为一个zip压缩文件:(Mule Zip文件并向FTP服务器发送压缩文件

我遇到骡子困难以下情形:

我创建了一个Spring bean,其中一个文件来在我想用ZipOutputStream类压缩这个文件,并通过它向我们的FTP

这是我的流程配置:

<flow name="testFlow" initialState="stopped"> 
    <file:inbound-endpoint path="${home.dir}/out" moveToDirectory="${hip.dir}/out/hist" fileAge="10000" responseTimeout="10000" connector-ref="input"/> 
    <component> 
     <spring-object bean="zipCompressor"/> 
    </component> 
    <set-variable value="#[message.inboundProperties.originalFilename]" variableName="originalFilename" /> 
    <ftp:outbound-endpoint host="${ftp.host}" port="${ftp.port}" user="${ftp.username}" password="${ftp.password}" path="${ftp.root.out}" outputPattern="#[flowVars['originalFilename']].zip" /> 
</flow> 

这是我zipCompressor的代码:

@Component 
public class ZipCompressor implements Callable { 

    private static final Logger LOG = LogManager.getLogger(ZipCompressor.class.getName()); 

    @Override 
    @Transactional 
    public Object onCall(MuleEventContext eventContext) throws Exception { 

     if (eventContext.getMessage().getPayload() instanceof File) { 
      final File srcFile = (File) eventContext.getMessage().getPayload(); 
      final String fileName = srcFile.getName(); 
      final File zipFile = new File(fileName + ".zip"); 

      try { 

       // create byte buffer 
       byte[] buffer = new byte[1024]; 
       FileOutputStream fos = new FileOutputStream(zipFile); 
       ZipOutputStream zos = new ZipOutputStream(fos); 
       FileInputStream fis = new FileInputStream(srcFile); 
       // begin writing a new ZIP entry, positions the stream to the start of the entry data 
       zos.putNextEntry(new ZipEntry(srcFile.getName())); 
       int length; 
       while ((length = fis.read(buffer)) > 0) { 
        zos.write(buffer, 0, length); 
       } 
       zos.closeEntry(); 
       // close the InputStream 
       fis.close(); 
       // close the ZipOutputStream 
       zos.close(); 
      } 
      catch (IOException ioe) { 
       LOG.error("Error creating zip file" + ioe); 
      } 
      eventContext.getMessage().setPayload(zipFile); 
     } 
     return eventContext.getMessage(); 
    } 
} 

我写了一个单元测试,压缩效果很好。使用正确的名称确实将文件传输到FTP,但zip文件无效,并且通过在NotePad ++中打开它,它只包含原始文件名。

我想我做错了将zip文件传递回骡流,但我现在卡住了,所以任何帮助将不胜感激!

+1

我跑你的流量和zipCompressor的副本。我也收到一个文件,但文件从不压缩。它处于原始状态。 – tbriscoe

回答

2

我已经实现了变压器这个

package com.test.transformer; 

import java.io.IOException; 
import java.io.InputStream; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipOutputStream; 

import org.apache.commons.io.IOUtils; 
import org.apache.commons.io.output.ByteArrayOutputStream; 
import org.mule.api.MuleMessage; 
import org.mule.api.transformer.TransformerException; 
import org.mule.transformer.AbstractMessageTransformer; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

public class ZipTransformer 
    extends AbstractMessageTransformer 
{ 
    private static final Logger log = LoggerFactory.getLogger(ZipTransformer.class); 
    public static final int DEFAULT_BUFFER_SIZE = 32768; 
    public static byte[] MAGIC = { 'P', 'K', 0x3, 0x4 }; 

    public ZipTransformer() 
    { 
    registerSourceType(InputStream.class); 
    registerSourceType(byte[].class); 
    } 

    public Object transformMessage(MuleMessage message, String outputEncoding) 
    throws TransformerException 
    { 
    Object payload = message.getPayload(); 
    try{ 
     byte[] data; 
     if (payload instanceof byte[]) 
     { 
      data = (byte[]) payload; 
     } 
     else if (payload instanceof InputStream) { 
      data = IOUtils.toByteArray((InputStream)payload); 
     } 
     else if (payload instanceof String) 
     { 
      data = ((String) payload).getBytes(outputEncoding); 
     } 
     else 
     { 
      data = muleContext.getObjectSerializer().serialize(payload); 
     } 
     return compressByteArray(data); 
    }catch (Exception ioex) 
    { 
     throw new TransformerException(this, ioex); 
    } 
    } 

    public Object compressByteArray(byte[] bytes) throws IOException 
    { 
     if (bytes == null || isCompressed(bytes)) 
     { 
      if (logger.isDebugEnabled()) 
      { 
       logger.debug("Data already compressed; doing nothing"); 
      } 
      return bytes; 
     } 

     if (logger.isDebugEnabled()) 
     { 
      logger.debug("Compressing message of size: " + bytes.length); 
     } 

     ByteArrayOutputStream baos = null; 
     ZipOutputStream zos = null; 

     try 
     { 
      baos = new ByteArrayOutputStream(DEFAULT_BUFFER_SIZE); 
      zos = new ZipOutputStream(baos); 
      zos.putNextEntry(new ZipEntry("test.txt")); 
      zos.write(bytes, 0, bytes.length); 
      zos.finish(); 
      zos.close(); 

      byte[] compressedByteArray = baos.toByteArray(); 

      baos.close(); 
      if (logger.isDebugEnabled()) 
      { 
       logger.debug("Compressed message to size: " + compressedByteArray.length); 
      } 

      return compressedByteArray; 
     } 
     catch (IOException ioex) 
     { 
      throw ioex; 
     } 
     finally 
     { 
      IOUtils.closeQuietly(zos); 
      IOUtils.closeQuietly(baos); 
     } 
    } 

    public boolean isCompressed(byte[] bytes) throws IOException 
    { 
     if ((bytes == null) || (bytes.length < 4)) 
     { 
      return false; 
     } 
     else 
     { 
      for (int i = 0; i < MAGIC.length; i++) { 
       if (bytes[i] != MAGIC[i]) { 
       return false; 
       } 
      } 
      return true; 
     } 
    } 


} 

用它作为

<custom-transformer class="com.test.transformer.ZipTransformer" doc:name="file zip transformer"/> 

截至目前设置文件名的test.txt。你可以改变使用任何属性或变量。

希望这会有所帮助。

+0

正是我需要的。我会尝试将其转换为使用@Transform注释。谢谢! –

1

更简单的方法是使用mule中的gzip转换器压缩文件。请注意,你必须通过xml来完成。

<gzip-compress-transformer/> 
+0

我知道,我起初使用gzip压缩,但要求是zip压缩,如我的文章的第一行所述。 –

0

在ZipTransformer构造函数中,不推荐使用以下内容。

registerSourceType(InputStream.class); 
registerSourceType(byte[].class); 

使用这个代替:

registerSourceType(DataTypeFactory.create(InputStream.class)); 
registerSourceType(DataTypeFactory.create(byte[].class));