前端与服务端传输文件时,需要双方需要进行解压缩,也就是Java序列化。可以使用java进行对象序列化,netty去传输,但java序列化硬伤太多(无法跨语言,码流太大,性能太低),所以最好使用主流的编辑码框架来配合netty使用。此处使用的是JBossMarshalling框架。
附下载链接
1,jboss-marshalling-1.3.0.CR9.jar
2,jboss-marshalling-serial-1.3.0.CR9.jar
package bhz.netty.serial;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class GZipUtils {
public static byte[] gzip(byte[] data) throws Exception{
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
gzipOutputStream.write(data);
gzipOutputStream.finish();
gzipOutputStream.close();
byte[] ret = byteArrayOutputStream.toByteArray();
byteArrayOutputStream.close();
return ret;
}
public static byte[] ungzip(byte[] data) throws Exception{
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);
GZIPInputStream gzipInputStream = new GZIPInputStream(byteArrayInputStream);
byte[] buf = new byte[1024];
int num = -1;
ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
while((num = gzipInputStream.read(buf,0,buf.length)) != -1) {
byteOutputStream.write(buf,0,num);
}
gzipInputStream.close();
byteArrayInputStream.close();
byte[] ret = byteOutputStream.toByteArray();
byteOutputStream.flush();
byteOutputStream.close();
return ret;
}
public static void main(String[] arg0) throws Exception{
String readPath = System.getProperty("user.dir")+File.separatorChar+"sources"+File.separatorChar+"001.png";
File file = new File(readPath);
FileInputStream inputStream = new FileInputStream(file);
byte[] data = new byte[inputStream.available()];
inputStream.read(data);
inputStream.close();
System.out.println("文件原始大小为:"+data.length);
//测试压缩
byte[] ret1 = GZipUtils.gzip(data);
System.out.println("压缩之后大小为:"+ret1.length);
//测试还原
byte[] ret2 = GZipUtils.ungzip(ret1);
System.out.println("还原时候大小为:"+ret2.length);
String writePath = System.getProperty("user.dir")+File.separatorChar+"receive"+File.separatorChar+"001.png";
FileOutputStream outputStream = new FileOutputStream(writePath);
outputStream.write(ret2);
outputStream.close();
}
}
package bhz.netty.serial;
import java.io.Serializable;
public class Request implements Serializable{
private static final long SerialVersionUID = 1L;
private String id;
private String name;
private String requestMessage;
private byte[] attachment;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRequestMessage() {
return requestMessage;
}
public void setRequestMessage(String requestMessage) {
this.requestMessage = requestMessage;
}
public byte[] getAttachment() {
return attachment;
}
public void setAttachment(byte[] attachment) {
this.attachment = attachment;
}
}
package bhz.netty.serial;
import java.io.Serializable;
public class Response implements Serializable{
private static final long SerialVersionUID = 1L;
private String id;
private String name;
private String responseMessage;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getResponseMessage() {
return responseMessage;
}
public void setResponseMessage(String responseMessage) {
this.responseMessage = responseMessage;
}
}
package bhz.netty.serial;
import org.jboss.marshalling.MarshallerFactory;
import org.jboss.marshalling.Marshalling;
import org.jboss.marshalling.MarshallingConfiguration;
import io.netty.handler.codec.marshalling.DefaultMarshallerProvider;
import io.netty.handler.codec.marshalling.DefaultUnmarshallerProvider;
import io.netty.handler.codec.marshalling.MarshallerProvider;
import io.netty.handler.codec.marshalling.MarshallingDecoder;
import io.netty.handler.codec.marshalling.MarshallingEncoder;
import io.netty.handler.codec.marshalling.UnmarshallerProvider;
public final class MarshallingCodeCFactory {
/*
* 创建JBoss Marshalling解码器MarshallingDecoder
* @return MarshallingDecoder
* */
public static MarshallingDecoder buildMarshallingDecoder() {
final MarshallerFactory marshallingFactory = Marshalling.getProvidedMarshallerFactory("serial");
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallingFactory, configuration);
//构件Netty的marshallingDecoder对象,两个参数分别为Provider和单个消息序列化后的最大长度
MarshallingDecoder decoder = new MarshallingDecoder(provider,1024*1024*1);
return decoder;
}
/*
* 创建Marshalling解码器 MarshallingEncoder
* return MarshallingEncoder
* */
public static MarshallingEncoder buildMarshallingEncoder() {
final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
final MarshallingConfiguration configuration = new MarshallingConfiguration();
configuration.setVersion(5);
MarshallerProvider provider = new DefaultMarshallerProvider(marshallerFactory, configuration);
MarshallingEncoder encoder = new MarshallingEncoder(provider);
return encoder;
}
}
package bhz.netty.serial;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
public class Server {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup worker = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(boss,worker)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG,1024)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel sc) throws Exception {
// TODO Auto-generated method stub
sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
sc.pipeline().addLast(new ServerHandler());
}
});
ChannelFuture channelFuture = bootstrap.bind(8888).sync();
channelFuture.channel().closeFuture().sync();
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}
package bhz.netty.serial;
import java.io.File;
import java.io.FileOutputStream;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
public class ServerHandler extends SimpleChannelInboundHandler {
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
// TODO Auto-generated method stub
Request request = (Request)msg;
System.out.println("Server :" + request.getId()+" , "+request.getName()+" , "+request.getRequestMessage());
byte[] attachment = GZipUtils.ungzip(request.getAttachment());
String path = System.getProperty("user.dir")+File.separatorChar+"receive"+File.separatorChar+"001.png";
FileOutputStream fileOutputStream = new FileOutputStream(path);
fileOutputStream.write(attachment);
fileOutputStream.close();
Response response = new Response();
response.setId(request.getId());
response.setName("response : "+request.getId());
response.setResponseMessage("相应内容 : "+request.getId());
ctx.writeAndFlush(response);
}
}
package bhz.netty.serial;
import java.io.File;
import java.io.FileInputStream;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
public class Client {
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
EventLoopGroup worker = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(worker)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel sc) throws Exception {
// TODO Auto-generated method stub
sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
sc.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
sc.pipeline().addLast(new ClientHandle());
}
});
ChannelFuture channelFuture = bootstrap.connect("127.0.0.1",8888).sync();
for(int i=0;i<5;i++) {
Request request = new Request();
request.setId(""+i);
request.setName("Pro"+i);
request.setRequestMessage("数据信息Client~Server:"+i);
String path = System.getProperty("user.dir") + File.separatorChar + "sources" + File.separatorChar + "001.png";
File file = new File(path);
FileInputStream inputStream = new FileInputStream(file);
byte[] data = new byte[inputStream.available()];
inputStream.read(data);
inputStream.close();
request.setAttachment(GZipUtils.gzip(data));
channelFuture.channel().writeAndFlush(request);
}
channelFuture.channel().closeFuture().sync();
worker.shutdownGracefully();
}
}
package bhz.netty.serial;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
public class ClientHandle extends SimpleChannelInboundHandler{
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
// TODO Auto-generated method stub
Response response = (Response)msg;
System.out.println("Client :" + response.getId()+" , "+response.getName()+" , "+response.getResponseMessage());
}
}
注意:先启动服务端,在启动客户端
可以看出,这里实现了客户端与服务端进行了对象的传输,不再是简单的String对象的传输,并进行了图片的编辑码处理(其他文件同理)。