I made a encoder/decoder can be uploaded to web application server by mina 2.0
It is difficult to manipulate byte stream in mina, because I could not estimate how many bytes sent.
So, the encoder just send file bytes stream, and meta-information.
The docoder stack the stream untile output of stream is end, process it.
If you are first in mina, its examples are useful.

Encoder

public class ImageUploadRequestEncoder extends ProtocolEncoderAdapter  {
 private static final Log log = LogFactory.getLog(ImageUploadRequestDecoder.class);
 
 private CharsetEncoder encoder;
 public ImageUploadRequestEncoder() {
  Charset charset = Charset.forName("UTF-8");
     encoder = charset.newEncoder();
 }
 
 @Override
 public void encode(IoSession session, Object obj, ProtocolEncoderOutput out) throws Exception {
  ImageUploadRequestData data = (ImageUploadRequestData) obj;
  
  IoBuffer buffer = IoBuffer.allocate(1, false);
     buffer.setAutoExpand(true);
    
     int StringLength = ImageUploadCodecFactory.DELIMITER.length() * 5 +
  data.getId().length() + data.getCompanyID().length() + data.getFromFileName().length() +
  data.getToDirName().length() + data.getPureFileName().length() + data.getPhase().name().length();
     int totalLength = 4 + data.getByteStreamLength() + 4 + StringLength;
     log.debug("total length : " + totalLength);
     buffer.putInt(totalLength);
     buffer.putInt(data.getByteStreamLength());
    
     buffer.put(data.getByteStream());
     buffer.putInt(StringLength);
     buffer.putString(data.getId(), encoder);
     buffer.putString(ImageUploadCodecFactory.DELIMITER, encoder);
     buffer.putString(data.getCompanyID(), encoder);
     buffer.putString(ImageUploadCodecFactory.DELIMITER, encoder);
     buffer.putString(data.getFromFileName(), encoder);
     buffer.putString(ImageUploadCodecFactory.DELIMITER, encoder);
     buffer.putString(data.getPureFileName(), encoder);
     buffer.putString(ImageUploadCodecFactory.DELIMITER, encoder);
     buffer.putString(data.getToDirName(), encoder);
     buffer.putString(ImageUploadCodecFactory.DELIMITER, encoder);
     buffer.putString(data.getPhase().name(), encoder);
     buffer.flip();
        out.write(buffer);
 }
 
}


Decoder


public class ImageUploadRequestDecoder extends CumulativeProtocolDecoder {
 private static final Log log = LogFactory.getLog(ImageUploadRequestDecoder.class);
 private static final int MIN_READ_LENGTH = 4;
 public static final int MAX_SIZE = 1024 * 1024 * 100;
 private IoBuffer savedBuffer = IoBuffer.allocate(4096, true);
 private int remainLength = 0;
 public ImageUploadRequestDecoder() {
  savedBuffer.setAutoExpand(true);
 }
 private boolean isFirst = false;
 @Override
 protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
  if (isDecodable(session, in) == MessageDecoderResult.NEED_DATA) {
   return false;
  }
  if (isFirst == false) {
   int byteStreamLength = getStreamLength(in);
   log.debug("byteStreamLength : " + byteStreamLength);
   if (byteStreamLength <= 0) {
    throw new IOException("Total length of file is negative : " + byteStreamLength);
   } else if (byteStreamLength >= MAX_SIZE) {
    log.warn("Total length of file is so big to receive : " + byteStreamLength);
   }
   log.debug("in.remaining() : " + in.remaining());
   if (in.remaining() == byteStreamLength) {
    savedBuffer.put(in);
    savedBuffer.flip();
    decodeBody(session, out);
    reset();
   } else { // not yet received
    isFirst = true;
    remainLength = byteStreamLength - in.remaining();
    savedBuffer.put(in);
    log.debug("not yet received");
   }
   return true;
  }
  int readableSize = remainLength - in.remaining();
  if (readableSize == 0) { // all received.
   savedBuffer.put(in);
   savedBuffer.flip();
   decodeBody(session, out);
   reset();
  } else { // more received.W
   isFirst = true;
   remainLength = remainLength - in.remaining();
   savedBuffer.put(in);
  }
  return true;
 }
 private void reset() {
  savedBuffer.clear();
  remainLength = 0;
  isFirst = false;
 }
 private void decodeBody(IoSession session, ProtocolDecoderOutput out) throws IOException {
  PushbackInputStream stream = new PushbackInputStream(savedBuffer.asInputStream(), savedBuffer.remaining());
  byte[] sizeArray = new byte[4];
  if (stream.read(sizeArray, 0, 4) < 0) {
   throw new IOException("wrong bytes transmitted.");
  }
  int size = byteArrayToInt(sizeArray);
  byte[] byteStream = new byte[size];
  int datasize = stream.read(byteStream, 0, size);
  ImageUploadRequestData data = new ImageUploadRequestData();
  data.setByteStream(byteStream);
  data.setByteStreamLength(datasize);
  sizeArray = new byte[4];
  datasize = stream.read(sizeArray, 0, 4);
  int StringLength = byteArrayToInt(sizeArray);
  byte[] strStream = new byte[StringLength];
  datasize = stream.read(strStream, 0, StringLength);
  String s = new String(strStream, "UTF-8");
  StringTokenizer tokenizer = new StringTokenizer(s, ImageUploadCodecFactory.DELIMITER);
  int i = 0;
  while (tokenizer.hasMoreTokens()) {
   // id : 1256117865031||KR12662||d:\a.txt||a.txt||e:\vuscript
   String token = tokenizer.nextToken();
   if (i == 0) {
    data.setId(token);
    ;
   } else if (i == 1) {
    data.setCompanyID(token);
    ;
   } else if (i == 2) {
    data.setFromFileName(token);
   } else if (i == 3) {
    data.setPureFileName(token);
   } else if (i == 4) {
    data.setToDirName(token);
   } else if (i == 5) {
    if (token.equals("alpha")) {
     data.setPhase(DEPLOYPHASE.alpha);
    } else if (token.equals("real")) {
     data.setPhase(DEPLOYPHASE.real);
    } else if (token.equals("cache")) {
     data.setPhase(DEPLOYPHASE.cache);
    }
   }
   i++;
  }
  out.write(data);
  //out.flush();
 }
 private MessageDecoderResult isDecodable(IoSession session, IoBuffer in) {
  if (in.remaining() < MIN_READ_LENGTH) {
   return MessageDecoderResult.NEED_DATA;
  }
  return MessageDecoderResult.OK;
 }
 protected int getStreamLength(IoBuffer iobuffer) throws Exception {
  if (iobuffer.remaining() >= 4) {
   return iobuffer.getInt();
  }
  return Integer.MIN_VALUE;
 }
 class Message {
  long bytesLength = -1;
  byte[] bytes;
 }
 private static int byteArrayToInt(byte[] b) {
  int value = 0;
  for (int i = 0; i < 4; i++) {
   int shift = (4 - 1 - i) * 8;
   value += (b[i] & 0x000000FF) << shift;
  }
  return value;
 }
}


CodecFactory

public class ImageUploadCodecFactory implements ProtocolCodecFactory {
    private ProtocolEncoder encoder;
    private ProtocolDecoder decoder;
    public static String DELIMITER = "||";
   
    public ImageUploadCodecFactory() {
        encoder = new ImageUploadRequestEncoder();
  decoder = new ImageUploadRequestDecoder();
    }
    public ProtocolEncoder getEncoder(IoSession ioSession) throws Exception {
        return encoder;
    }
    public ProtocolDecoder getDecoder(IoSession ioSession) throws Exception {
        return decoder;
    }
}
Posted by 김용환 '김용환'

댓글을 달아 주세요