使用Netty作为底层框架,开发文件上传系统。SpringBoot+Netty+SpringTask。搭建过程2

1、文件上传时请求的消息类型

@Data
public class FilePacketRequestMessage extends Message{

//文件名称
    private String file_md5;
//字节读取开始位置
    private long startPos;
    private byte[] bytes;
//字节读取结束位置
    private int endPos;
//本次发送总字节数
    private long totalLen;
//上传文件的路径,防止文件过大多次上传
    private String filePath;

    public FilePacketRequestMessage() {
    }

    @Override
    public int getMessageType() {
        return UploadOABak;
    }
}

2、将读取到的最新备份封装到消息类型中并发送给服务端

@Slf4j
public class SendFile {

    private static RandomAccessFile randomAccessFile = null;

    public static void sendFileByByte(Channel channel, File file,long start) throws IOException {
        String filename = file.getName();
        String bakPath = file.getPath();
        randomAccessFile = new RandomAccessFile(bakPath,"r");
        byte[] bytes = new byte[1024];
        int byteRead = 0;

        FilePacketRequestMessage fileRequest = new FilePacketRequestMessage();
        fileRequest.setFile_md5(filename);
        fileRequest.setStartPos(start);
        randomAccessFile.seek(fileRequest.getStartPos());
        long totalLen = bakPath.length();
        long end = totalLen - start;
        log.info("传输文件第 {} 字节,共有{} 字节,还剩余{}未上传", start,totalLen,end);
        fileRequest.setTotalLen(totalLen);
        if ((byteRead = randomAccessFile.read(bytes))!= -1 && (randomAccessFile.length()-start)>0){
            fileRequest.setEndPos(byteRead);
            fileRequest.setBytes(bytes);
            fileRequest.setFilePath(bakPath);
            channel.writeAndFlush(fileRequest);
            randomAccessFile.close();
        }else{
            randomAccessFile.close();
            channel.close();
            System.out.println("文件读取完成");
        }
    }

3、如果备份过大可能要拆分成多块进行上传

创建文件上传响应类型,监控已经上传完成度进度

并通过已经完成的进度作为开始再读取1024个字节作为下次要发送的数据

@Data
public class FileUploadResultResponseMessage extends AbstractResponseMessage{

    private Long start;

    private String filePath;

    public FileUploadResultResponseMessage(Long start, String filePath) {
        this.start = start;
        this.filePath = filePath;
    }

    public FileUploadResultResponseMessage(boolean success, String reason, Long start, String filePath) {
        super(success, reason);
        this.start = start;
        this.filePath = filePath;
    }

    @Override
    public int getMessageType() {
        return UploadResult;
    }
}

4、读取服务端响应的消息,以上次结束的位置作为本次读取数据的开始进行上传。

@Slf4j
@Component
@ChannelHandler.Sharable
public class TransferFileHandler extends SimpleChannelInboundHandler<FileUploadResultResponseMessage> {


    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FileUploadResultResponseMessage in) throws Exception {
        if (!in.getSuccess()) {
            String filePath = in.getFilePath();
            Long start = in.getStart();
            File file = new File(filePath);
            SendFile.sendFileByByte(ctx.channel(), file, start);
        }
    }
}

5、配置自动任务,定时定点调用文件上传的方法。

    为防止网络异常应使用心跳机制实时感应客户端或服务端是否在线。

@Component
public class XXLJobTask {

    @Value("${netty.uploadDir}")
    private String uploadDir;

    @Scheduled(initialDelay = 12000,fixedDelay = 1000*3600)
    public void uploadFileTask(){

        Channel channel = NettyClient.getChannel();
        File bakPath = selectFileToUpload(Paths.get(uploadDir));
        try {
            SendFile.sendFileByByte(channel,bakPath,0);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

  • 30
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

工作这么多年,学会了内卷

共同加油,继续努力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值