MINA 传送文件 文件名 .

7 篇文章 0 订阅
6 篇文章 0 订阅

http://blog.csdn.net/huaye2007/article/details/7737487

网上查了堆资料,传送文件名都是写死了的。那如何同时传送文件和文件名?这就要用到Mina 的编码和解码,在刚接触mina的时候,大家可以先看下这个pdf   Apache_Mina_Server_2.0中文参考手册V1.0.pdf       这个文档刚开始一般大家都会很容易传送字符串,但是到传送文件就有点难了。

直接介绍编码和解码了:

  1. package com.blazefire.client;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileNotFoundException;  
  6.   
  7. import org.apache.mina.core.service.IoHandlerAdapter;  
  8. import org.apache.mina.core.session.IoSession;  
  9.   
  10. import com.blazefire.bean.BaseMessage;  
  11. import com.blazefire.bean.FileBean;  
  12. import com.blazefire.util.BeanUtil;  
  13. import com.blazefire.util.FileHelper;  
  14.   
  15. public class ClientHandler extends IoHandlerAdapter{  
  16.       
  17.     /** 
  18.      * 客户端接收到信息 
  19.      * */  
  20.     public void messageReceived(IoSession session, Object message)  
  21.             throws Exception {  
  22.         // TODO Auto-generated method stub   
  23.         super.messageReceived(session, message);  
  24.           
  25.     }  
  26.   
  27.     public void sessionOpened(IoSession session) {   
  28.         BaseMessage baseMessage = new BaseMessage();  
  29.         baseMessage.setDataType(BeanUtil.UPLOAD_FILE);  
  30.         FileBean bean = new FileBean();  
  31.         File file = new File("e:\\中国.jpg");  
  32.         bean.setFileName(file.getName());  
  33.         bean.setFileSize((int)file.length());  
  34.         try {  
  35.             FileHelper helper =new FileHelper();  
  36.             bean.setFileContent(helper.getContent(file));  
  37.         } catch (Exception e) {  
  38.             // TODO Auto-generated catch block   
  39.             e.printStackTrace();  
  40.         }  
  41.         baseMessage.setData(bean);  
  42.         session.write(baseMessage);   
  43.     }  
  44.   
  45.     public void sessionCreated(IoSession session) throws Exception {  
  46.         // TODO Auto-generated method stub   
  47.         super.sessionCreated(session);  
  48.     }  
  49.       
  50.       
  51. }  
package com.blazefire.client;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;

import com.blazefire.bean.BaseMessage;
import com.blazefire.bean.FileBean;
import com.blazefire.util.BeanUtil;
import com.blazefire.util.FileHelper;

public class ClientHandler extends IoHandlerAdapter{
	
	/**
	 * 客户端接收到信息
	 * */
	public void messageReceived(IoSession session, Object message)
			throws Exception {
		// TODO Auto-generated method stub
		super.messageReceived(session, message);
		
	}

	public void sessionOpened(IoSession session) { 
		BaseMessage baseMessage = new BaseMessage();
		baseMessage.setDataType(BeanUtil.UPLOAD_FILE);
		FileBean bean = new FileBean();
		File file = new File("e:\\中国.jpg");
		bean.setFileName(file.getName());
		bean.setFileSize((int)file.length());
		try {
			FileHelper helper =new FileHelper();
			bean.setFileContent(helper.getContent(file));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		baseMessage.setData(bean);
		session.write(baseMessage); 
	}

	public void sessionCreated(IoSession session) throws Exception {
		// TODO Auto-generated method stub
		super.sessionCreated(session);
	}
	
	
}

在连接成功后,调用sessionOpened方法,读取本地文件,向服务器传送文件,其中用到的一些类将在文章末尾贴出。

传送文件需要文件名,文件大小,文件byte数组:  文件名这个不用说,文件大小是为了解码的时候知道读取到哪个字节就可以停止了。文件byte数组 存储文件内容

  1. BaseMessage baseMessage = new BaseMessage();  
  2. baseMessage.setDataType(BeanUtil.UPLOAD_FILE);//BeanUtil.UPLOAD_FILE值为1  
BaseMessage baseMessage = new BaseMessage();
baseMessage.setDataType(BeanUtil.UPLOAD_FILE);//BeanUtil.UPLOAD_FILE值为1
准备好这些信息之后,调用session.write方法开始编码。

  1. package com.blazefire.util;  
  2.   
  3. import java.nio.charset.Charset;  
  4.   
  5. import org.apache.mina.core.buffer.IoBuffer;  
  6. import org.apache.mina.core.session.IoSession;  
  7. import org.apache.mina.filter.codec.ProtocolEncoderOutput;  
  8. import org.apache.mina.filter.codec.demux.MessageEncoder;  
  9.   
  10. import com.blazefire.bean.BaseMessage;  
  11. import com.blazefire.bean.FileBean;  
  12.   
  13. public class BaseMessageEncoder implements MessageEncoder<BaseMessage> {  
  14.   
  15.     /** 
  16.      * 基本信息编码 
  17.      * */  
  18.     public void encode(IoSession session, BaseMessage message,ProtocolEncoderOutput outPut) throws Exception {  
  19.         // TODO Auto-generated method stub   
  20.         IoBuffer buffer = IoBuffer.allocate(1024*1024*50);   
  21.         buffer.putInt(message.getDataType());  
  22.         FileBean bean = (FileBean) message.getData();  
  23.         byte[] byteStr = bean.getFileName().getBytes(BeanUtil.charset);  
  24.         buffer.putInt(byteStr.length);  
  25.         buffer.putInt(bean.getFileSize());  
  26.         buffer.put(byteStr);  
  27.         buffer.put(bean.getFileContent());  
  28.         buffer.flip();  
  29.         outPut.write(buffer);  
  30.         System.out.println("编码完成!");  
  31.     }  
  32.   
  33. }  
package com.blazefire.util;

import java.nio.charset.Charset;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
import org.apache.mina.filter.codec.demux.MessageEncoder;

import com.blazefire.bean.BaseMessage;
import com.blazefire.bean.FileBean;

public class BaseMessageEncoder implements MessageEncoder<BaseMessage> {

	/**
	 * 基本信息编码
	 * */
	public void encode(IoSession session, BaseMessage message,ProtocolEncoderOutput outPut) throws Exception {
		// TODO Auto-generated method stub
		IoBuffer buffer = IoBuffer.allocate(1024*1024*50); 
		buffer.putInt(message.getDataType());
		FileBean bean = (FileBean) message.getData();
		byte[] byteStr = bean.getFileName().getBytes(BeanUtil.charset);
		buffer.putInt(byteStr.length);
		buffer.putInt(bean.getFileSize());
		buffer.put(byteStr);
		buffer.put(bean.getFileContent());
		buffer.flip();
		outPut.write(buffer);
		System.out.println("编码完成!");
	}

}
buffer.putInt(message.getDataType());首先放入了一个int值1 放入这个值,主要是因为这个项目要用到多个解码器,针对不同的信息进行不同的编码,在解码的时候会根据这个参数来判断是否要用这个解码器来解码。

byte[] byteStr = bean.getFileName().getBytes(BeanUtil.charset); 将字符串转换成byte数组,BeanUtil.charset   Charset charset = Charset.forName("utf-8"); utf-8编码

buffer.putInt(byteStr.length);  记录文件名的byte数组长度
buffer.putInt(bean.getFileSize()); 记录文件的byte数组长度

buffer.put(byteStr); 存入到buffer
buffer.put(bean.getFileContent());存入到buffer

编码就到此完成了。

现在开始服务器的解码:

  1. package com.blazefire.util;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.nio.charset.Charset;  
  6.   
  7. import org.apache.mina.core.buffer.IoBuffer;  
  8. import org.apache.mina.core.session.AttributeKey;  
  9. import org.apache.mina.core.session.IoSession;  
  10. import org.apache.mina.filter.codec.CumulativeProtocolDecoder;  
  11. import org.apache.mina.filter.codec.ProtocolDecoderOutput;  
  12. import org.apache.mina.filter.codec.demux.MessageDecoder;  
  13. import org.apache.mina.filter.codec.demux.MessageDecoderResult;  
  14.   
  15. import com.blazefire.bean.BaseMessage;  
  16. import com.blazefire.bean.FileBean;  
  17.   
  18. public class BaseMessageDecoder  implements MessageDecoder {  
  19.     private AttributeKey CONTEXT = new AttributeKey(getClass(), "context");  
  20.     /** 
  21.      * 是否适合解码 
  22.      * */  
  23.     public MessageDecoderResult decodable(IoSession session, IoBuffer in) {  
  24.         // TODO Auto-generated method stub   
  25.         Context context = (Context) session.getAttribute(CONTEXT);  
  26.         if(context == null){  
  27.             context = new Context();  
  28.             context.dataType = in.getInt();  
  29.             if(context.dataType == BeanUtil.UPLOAD_FILE){  
  30.                 context.strLength = in.getInt();  
  31.                 context.byteStr = new byte[context.strLength];  
  32.                 context.fileSize = in.getInt();  
  33.                 context.byteFile = new byte[context.fileSize];  
  34.                 session.setAttribute(CONTEXT, context);  
  35.                 return MessageDecoderResult.OK;  
  36.             }else{  
  37.                 return MessageDecoderResult.NOT_OK;  
  38.             }  
  39.         }else{  
  40.             if(context.dataType == BeanUtil.UPLOAD_FILE){  
  41.                 return MessageDecoderResult.OK;  
  42.             }else{  
  43.                 return MessageDecoderResult.NOT_OK;  
  44.             }  
  45.         }  
  46.     }  
  47.   
  48.     /** 
  49.      * 数据解码 
  50.      * */  
  51.     public MessageDecoderResult decode(IoSession session, IoBuffer in,  
  52.             ProtocolDecoderOutput outPut) throws Exception {  
  53.         // TODO Auto-generated method stub   
  54.         System.out.println("开始解码:");  
  55.         Context context = (Context) session.getAttribute(CONTEXT);  
  56.         if(!context.init){  
  57.             context.init = true;  
  58.             in.getInt();  
  59.             in.getInt();  
  60.             in.getInt();  
  61.         }  
  62.         byte[] byteFile = context.byteFile;  
  63.         int count = context.count;  
  64.         while(in.hasRemaining()){  
  65.             byte b = in.get();  
  66.             if(!context.isReadName){  
  67.                 context.byteStr[count] = b;  
  68.                 if(count == context.strLength-1){  
  69.                     context.fileName = new String(context.byteStr,BeanUtil.charset);  
  70.                     System.out.println(context.fileName);  
  71.                     count = -1;  
  72.                     context.isReadName = true;  
  73.                 }  
  74.             }  
  75.             if(context.isReadName && count != -1){  
  76.                 byteFile[count] = b;  
  77.             }  
  78.         //  byteFile[count] = b;   
  79.             count++;  
  80.         }  
  81.         context.count = count;  
  82.         System.out.println("count:"+count);  
  83.         System.out.println("context.fileSize:"+context.fileSize);  
  84.         session.setAttribute(CONTEXT, context);  
  85.         if(context.count == context.fileSize){  
  86.             BaseMessage message = new BaseMessage();  
  87.             message.setDataType(context.dataType);  
  88.             FileBean bean = new FileBean();  
  89.             bean.setFileName(context.fileName);  
  90.             bean.setFileSize(context.fileSize);  
  91.             bean.setFileContent(context.byteFile);  
  92.             message.setData(bean);  
  93.             outPut.write(message);  
  94.             context.reset();  
  95.         }  
  96.         return MessageDecoderResult.OK;  
  97.     }  
  98.   
  99.     /** 
  100.      *  
  101.      * */  
  102.     public void finishDecode(IoSession session, ProtocolDecoderOutput outPut)  
  103.             throws Exception {  
  104.         // TODO Auto-generated method stub   
  105.         System.out.println("end:::::::::::::::::");  
  106.     }  
  107.     private class Context{  
  108.         public int dataType;  
  109.         public byte[] byteFile;  
  110.         public int count;  
  111.         public int strLength;  
  112.         public boolean isReadName;  
  113.         public int fileSize;  
  114.         public byte[] byteStr;  
  115.         public String fileName;  
  116.         public boolean init = false;  
  117.           
  118.         public void reset(){  
  119.             dataType = 0;  
  120.             byteFile = null;  
  121.             count = 0;  
  122.             strLength = 0;  
  123.             isReadName = false;  
  124.             fileSize = 0;  
  125.             byteStr = null;  
  126.             fileName = null;  
  127.               
  128.         }  
  129.     }  
  130.   
  131.   
  132. }  
package com.blazefire.util;

import java.io.File;
import java.io.FileOutputStream;
import java.nio.charset.Charset;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.AttributeKey;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.mina.filter.codec.demux.MessageDecoder;
import org.apache.mina.filter.codec.demux.MessageDecoderResult;

import com.blazefire.bean.BaseMessage;
import com.blazefire.bean.FileBean;

public class BaseMessageDecoder  implements MessageDecoder {
	private AttributeKey CONTEXT = new AttributeKey(getClass(), "context");
	/**
	 * 是否适合解码
	 * */
	public MessageDecoderResult decodable(IoSession session, IoBuffer in) {
		// TODO Auto-generated method stub
		Context context = (Context) session.getAttribute(CONTEXT);
		if(context == null){
			context = new Context();
			context.dataType = in.getInt();
			if(context.dataType == BeanUtil.UPLOAD_FILE){
				context.strLength = in.getInt();
				context.byteStr = new byte[context.strLength];
				context.fileSize = in.getInt();
				context.byteFile = new byte[context.fileSize];
				session.setAttribute(CONTEXT, context);
				return MessageDecoderResult.OK;
			}else{
				return MessageDecoderResult.NOT_OK;
			}
		}else{
			if(context.dataType == BeanUtil.UPLOAD_FILE){
				return MessageDecoderResult.OK;
			}else{
				return MessageDecoderResult.NOT_OK;
			}
		}
	}

	/**
	 * 数据解码
	 * */
	public MessageDecoderResult decode(IoSession session, IoBuffer in,
			ProtocolDecoderOutput outPut) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("开始解码:");
		Context context = (Context) session.getAttribute(CONTEXT);
		if(!context.init){
			context.init = true;
			in.getInt();
			in.getInt();
			in.getInt();
		}
		byte[] byteFile = context.byteFile;
		int count = context.count;
		while(in.hasRemaining()){
			byte b = in.get();
			if(!context.isReadName){
				context.byteStr[count] = b;
				if(count == context.strLength-1){
					context.fileName = new String(context.byteStr,BeanUtil.charset);
					System.out.println(context.fileName);
					count = -1;
					context.isReadName = true;
				}
			}
			if(context.isReadName && count != -1){
				byteFile[count] = b;
			}
		//	byteFile[count] = b;
			count++;
		}
		context.count = count;
		System.out.println("count:"+count);
		System.out.println("context.fileSize:"+context.fileSize);
		session.setAttribute(CONTEXT, context);
		if(context.count == context.fileSize){
			BaseMessage message = new BaseMessage();
			message.setDataType(context.dataType);
			FileBean bean = new FileBean();
			bean.setFileName(context.fileName);
			bean.setFileSize(context.fileSize);
			bean.setFileContent(context.byteFile);
			message.setData(bean);
			outPut.write(message);
			context.reset();
		}
		return MessageDecoderResult.OK;
	}

	/**
	 * 
	 * */
	public void finishDecode(IoSession session, ProtocolDecoderOutput outPut)
			throws Exception {
		// TODO Auto-generated method stub
		System.out.println("end:::::::::::::::::");
	}
	private class Context{
		public int dataType;
		public byte[] byteFile;
		public int count;
		public int strLength;
		public boolean isReadName;
		public int fileSize;
		public byte[] byteStr;
		public String fileName;
		public boolean init = false;
		
		public void reset(){
			dataType = 0;
			byteFile = null;
			count = 0;
			strLength = 0;
			isReadName = false;
			fileSize = 0;
			byteStr = null;
			fileName = null;
			
		}
	}


}
decodable方法就是判断是否要用当前这个解码器

如果你看过上面提到的pdf中 对于这个 CumulativeProtocolDecoder解码器的一些介绍和使用,特别是复杂的解码器的说明这块

你就会知道为什么这里会用到 CONTEXT 这个属性,因为编码的时候,文件内容较长,分成了许多数据包,这个时候在解码的时候就需要记录解码到那个字节,下次再解码的时候就从这个字节开始。

这里需要说下注意点  当前解码器实现的是MessageDecoder这个接口。而pdf中解码器是继承 CumulativeProtocolDecoder这个类。

CumulativeProtocolDecoder这个类 在doDecode方法中需要自己去判断是否需要继续调用doDecode这个方法来完成解码。如果还需要数据解码,这返回值为true,如果解码已完成则直接返回false.

而MessageDecoder这个接口不需要自己去判断

这个类会自己调用自己来将数据传送完,所以每次都会调用这个类里面的方法,每次都会将成员变量初始化.

解码这块主要是解决多个数据包的解码拼成一条完成的消息,这个问题解决了,就没有啥难题了。

  1. if(!context.init){  
  2.             context.init = true;  
  3.             in.getInt();  
  4.             in.getInt();  
  5.             in.getInt();  
  6.         }  
if(!context.init){
			context.init = true;
			in.getInt();
			in.getInt();
			in.getInt();
		}

加这个是将那些传入的整数字节读取掉,只剩下文件名的字节和文件字节。

读取完之后,记得重置context的值,否则将影响后续文件的读取。

处理完这些之后,就是直接写文件了。

  1. package com.blazefire.server;  
  2.   
  3. import java.io.FileOutputStream;  
  4.   
  5. import org.apache.mina.core.service.IoHandlerAdapter;  
  6. import org.apache.mina.core.session.IoSession;  
  7.   
  8. import com.blazefire.bean.BaseMessage;  
  9. import com.blazefire.bean.FileBean;  
  10.   
  11. public class ServerHandler extends IoHandlerAdapter{  
  12.   
  13.   
  14.     public void sessionCreated(IoSession session) throws Exception {  
  15.         // TODO Auto-generated method stub   
  16.         super.sessionCreated(session);  
  17.     }  
  18.   
  19.     public void sessionOpened(IoSession session) throws Exception {  
  20.         // TODO Auto-generated method stub   
  21.         super.sessionOpened(session);  
  22.     }  
  23.     /** 
  24.      * 服务器接收到消息 
  25.      * */  
  26.     public void messageReceived(IoSession session, Object message)  
  27.             throws Exception {  
  28.         // TODO Auto-generated method stub   
  29.         super.messageReceived(session, message);  
  30.         System.out.println("==============");  
  31.         BaseMessage baseMessage = (BaseMessage) message;  
  32.         FileBean bean = (FileBean) baseMessage.getData();  
  33.         System.out.println(bean.getFileName());  
  34.         FileOutputStream os = new FileOutputStream("f:\\"+bean.getFileName());  
  35.         os.write(bean.getFileContent());  
  36.         os.close();  
  37.     }  
  38.   
  39.   
  40.     public void exceptionCaught(IoSession session, Throwable cause)  
  41.             throws Exception {  
  42.         // TODO Auto-generated method stub   
  43.         super.exceptionCaught(session, cause);  
  44.     }  
  45. }  
package com.blazefire.server;

import java.io.FileOutputStream;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;

import com.blazefire.bean.BaseMessage;
import com.blazefire.bean.FileBean;

public class ServerHandler extends IoHandlerAdapter{


	public void sessionCreated(IoSession session) throws Exception {
		// TODO Auto-generated method stub
		super.sessionCreated(session);
	}

	public void sessionOpened(IoSession session) throws Exception {
		// TODO Auto-generated method stub
		super.sessionOpened(session);
	}
	/**
	 * 服务器接收到消息
	 * */
	public void messageReceived(IoSession session, Object message)
			throws Exception {
		// TODO Auto-generated method stub
		super.messageReceived(session, message);
		System.out.println("==============");
		BaseMessage baseMessage = (BaseMessage) message;
		FileBean bean = (FileBean) baseMessage.getData();
		System.out.println(bean.getFileName());
		FileOutputStream os = new FileOutputStream("f:\\"+bean.getFileName());
		os.write(bean.getFileContent());
		os.close();
	}


	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {
		// TODO Auto-generated method stub
		super.exceptionCaught(session, cause);
	}
}

mina这块刚开始对编码解码也不是很熟悉,后来还是根据别人的代码,自己测试才最终出了这个版本。本只想让大家自己自己动手做出来,这样也可以更深入了解。为了方便大家,还是贴下源码算了。

源码下载

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值