gpt4 book ai didi

java - 我可以只关闭fileoutputstream,但在通过Netty发送文件后 channel 仍然存在吗?

转载 作者:行者123 更新时间:2023-12-02 10:52:35 25 4
gpt4 key购买 nike

几天前,我在纠结如何在不杀死NettyServer的情况下访问NettyClient发送的文件。我在 StackOverFlow 上得到了解决方案,问题的详细信息是 here 。解决办法是客户端发送文件后关闭channel,服务器在channelInactive方法中关闭fileoutputstream。主要代码如下。

ClientHandler

public class FileClientHandler extends ChannelInboundHandlerAdapter {

private int readLength = 128;

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
sendFile(ctx.channel());
}

private void sendFile(Channel channel) throws IOException {
File file = new File("C:\\Users\\xxx\\Desktop\\1.png");
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);

ChannelFuture lastFuture = null;
for (;;) {
byte[] bytes = new byte[readLength];
int readNum = bis.read(bytes, 0, readLength);
if (readNum == -1) { // The end of the stream has been reached
bis.close();
fis.close();
lastFuture = sendToServer(bytes, channel, 0);
if(lastFuture == null) { // When our file is 0 bytes long, this is true
channel.close();
} else {
lastFuture.addListener(ChannelFutureListener.CLOSE);
}
return;
}
lastFuture = sendToServer(bytes, channel, readNum);
}
}

private ChannelFuture sendToServer(byte[] bytes, Channel channel, int length)
throws IOException {
return channel.writeAndFlush(Unpooled.copiedBuffer(bytes, 0, length));
}

}

服务器处理程序

public class FileServerHandler extends ChannelInboundHandlerAdapter {

private File file = new File("C:\\Users\\xxx\\Desktop\\2.png");
private FileOutputStream fos;

public FileServerHandler() {
try {
if (!file.exists()) {
file.createNewFile();
} else {
file.delete();
file.createNewFile();
}
fos = new FileOutputStream(file);
} catch (IOException e) {
e.printStackTrace();
}
}

@Override
public void channelInactive(ChannelHandlerContext ctx) {
System.out.println("I want to close fileoutputstream!");
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
ByteBuf buf = (ByteBuf) msg;
try {
buf.readBytes(fos, buf.readableBytes());
} catch (Exception e) {
e.printStackTrace();
} finally {
buf.release(); // Should always be done, even if writing to the file fails
}
}

}

如果现在我需要发送1万张图片,但每张图片都小如1KB。我必须经常关闭然后建立 channel 。这是一件浪费很多资源的事情。如何仅关闭 fileoutputstream 但 channel 处于 Activity 状态?

最佳答案

这只是一个想法,我还没有测试过它,但您可以在发送的位置启动一个流,而不是在自己的连接中发送每个文件:

  1. 要发送的文件数量(一次)
  2. 文件信息和内容(每个文件)
    1. 文件大小
    2. 文件名大小
    3. 文件名
    4. 文件内容(字节)

客户端看起来像这样:

public void sendFiles(Channel channel, File...files) {
ByteBufAllocator allocator = PooledByteBufAllocator.DEFAULT;
int fileCount = files.length;
// Send the file count
channel.write(allocator.buffer(4).writeInt(fileCount));
// For each file
Arrays.stream(files).forEach(f -> {
try {
// Get the file content
byte[] content = Files.readAllBytes(f.toPath());
byte[] fileName = f.getAbsolutePath().getBytes(UTF8);
// Write the content size, filename and the content
channel.write(allocator.buffer(4 + content.length + fileName.length)
.writeInt(content.length)
.writeInt(fileName.length)
.writeBytes(fileName)
.writeBytes(content)
);
} catch (IOException e) {
throw new RuntimeException(e); // perhaps do something better here.
}
});
// Flush the channel
channel.flush();
}

在服务器端,您需要一个稍微复杂的 channel 处理程序。我正在考虑重放解码器。 (Example here)

在该示例中,解码器将读取所有文件,然后转发到下一个处理程序,该处理程序将接收 Upload 实例列表,但您可以在每个收到文件后将每个上传发送到管道所以你不会分配那么多的内存。但其目的是在一个流中发送所有文件,而不是必须为每个文件连接/断开连接。

关于java - 我可以只关闭fileoutputstream,但在通过Netty发送文件后 channel 仍然存在吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52054490/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com