netty文件上传断点续传的演示

Netty文件上传断点续传的演示

一、理论和协议规范和工具类等

1、实现原理:

    netty文件上传采用自定义的协议方式实现,断点续传主要是依据RandomAccessFile类的随机读写能力,主要流程是客户端发起请求,将需要上传文件名称、路径、读取文件的数据、以及读取文件的起始位置等等信息,并且缓存在服务端中(以文件路径为key,自定义协议对象为value),服务端拿到客户端发送的上述数据,就会写文件,并且写完文件,也会记录写过数据位置等信息,再次发送信息给客户端下一次需要读取的数据。

    假如这个过程中,客户端断开了链接,此时由于服务端缓存了已经写过文件的位置,那么只会从写过文件的位置进行读文件,再传文件给服务端写等循环操作,从而达到了断点续茶传的效果。

 2、RandomAccessFile的基本使用

     *  RandomAccessFile的基本api
     * .getFilePointer : 获取当前操作的位置
     * .seek(index): 将操作位置设置到index
     * .read(byte):读文件到byte数组中,返回读取文件的长度
     * 
     * 构造函数
     *  rf = new RandomAccessFile(new File(filePath),"r"); // 参数2是模式
     *  
       *    模式详解:
     *    “r” 以只读方式来打开指定文件夹。如果试图对该RandomAccessFile执行写入方法,都将抛出IOException异常。
     *    “rw” 以读,写方式打开指定文件。如果该文件尚不存在,则试图创建该文件。
     *    “rws” 以读,写方式打开指定文件。相对于”rw” 模式,还要求对文件内容或元数据的每个更新都同步写入到底层设备。
     *    “rwd” 以读,写方式打开指定文件。相对于”rw” 模式,还要求对文件内容每个更新都同步写入到底层设备。

	 * 测试1:下面演示基本的读文件操作。
	 */
	@Test
	public void test1() throws IOException {
		String filePath = "src/d00_file/a.txt";
		RandomAccessFile rf = null;
		try {
			rf = new RandomAccessFile(new File(filePath), "r");
			System.out.println("输入内容:" + rf.getFilePointer());
			// 从10位置操作
			rf.seek(10);
			byte[] b = new byte[1024];
			int len = 0;
			// 循环读写 (len是读取的长度)
			while ((len = rf.read(b)) > 0) {
				System.out.print(new String(b, 0, len));
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			rf.close();
		}
	}
	
	/**
	 * 测试2: 向文件追加内容
	 */
	@Test
	public void test2() throws IOException{
        String filePath="src/d00_file/a.txt";
        RandomAccessFile rf=null;
        try {
			rf = new RandomAccessFile(new File(filePath), "rw");
			// 将操作指针移动到文件的最后
			rf.seek(rf.length());
			// 向文件写出数据
			rf.write("这是追加的内容。。".getBytes());
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            rf.close();
        }
    }
	
	/**
	 * 测试3:修改文件内容
	 */
	@Test
	public void test3() {
		RandomAccessFile rf = null;
		String oldStr = "www.www.www";
		String newStr = "hahahaha";
		try {
			rf = new RandomAccessFile("src/d00_file/a.txt", "rw");
			String line = null;
			// 记录上次操作点
			long lastpoint = 0;
			while ((line = rf.readLine()) != null) {
				long ponit = rf.getFilePointer();
				// 如果包含替换字符串
				if (line.contains(oldStr)) {
					// 替换字符串
					String str = line.replace(oldStr, newStr);
					// 恢复到上次读取位置 (readLine前的位置)
					rf.seek(lastpoint);
					// 重写行数据
					if (oldStr.length() != newStr.length()) {
						byte[] newb = Arrays.copyOf(str.getBytes(), line.getBytes().length);
						rf.write(newb);
						// lastpoint = lastpoint + newb.length;
						lastpoint = rf.getFilePointer();
						continue;
					} else {
						rf.write(str.getBytes());
					}
				}
				lastpoint = ponit;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				rf.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

 3、传输对象和协议对象设计

传输对象分为三种,一种是客户端发送给服务端的起始传输信息类、一种是分片文件数据类、一种是服务端返回给客户端分片文件指令类。

协议对象就是包含二个字段,一个是类型(上面三个对象的类型),一个是obejct字段,表示传输对象。

常量:

/**
 * 文件传输常量
 */
public class Constants {

    /**
     * 文件传输状态的标示
     */
    public static class FileStatus{
        public static int BEGIN = 0;    //开始
        public static int CENTER = 1;   //中间
        public static int END = 2;      //结尾
        public static int COMPLETE = 3; //完成
    }

    /**
     * 协议对象的传输对象类型
     */
    public static class TransferType{
        public static int REQUEST = 0;    //文件信息类型
        public static int INSTRUCT = 1;   //文件指令类型
        public static int DATA = 2;       //文件分片类型
    }

}

协议对象:

public class FileTransferProtocol {

	private Integer transferType; // 类型
	private Object transferObj; // 数据对象;(0)FileDescInfo、(1)FileBurstInstruct、(2)FileBurstData

	public Integer getTransferType() {
		return transferType;
	}

	public void setTransferType(Integer transferType) {
		this.transferType = transferType;
	}

	public Object getTransferObj() {
		return transferObj;
	}

	public void setTransferObj(Object transferObj) {
		this.transferObj = transferObj;
	}

}

文件传输相关对象:

/
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Java8新特性及实战视频教程完整版Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。这种风格将要处理的元素集合看作一种流, 流在管道中输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。 Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数递进方法中)。使用Lambda 表达式可以使代码变的更加简洁紧凑。Java8实战视频-01让方法参数具备行为能力Java8实战视频-02Lambda表达式初探Java8实战视频-03Lambda语法精讲Java8实战视频-04Lambda使用深入解析Java8实战视频-05Lambda方法推导详细解析-上.wmvJava8实战视频-06Lambda方法推导详细解析-下Java8实战视频-07Stream入门及Stream在JVM中的线程表现Java8实战视频-08Stream知识点总结Stream源码阅读Java8实战视频-09如何创建Stream上集Java8实战视频-10如何创建Stream下集.wmvJava8实战视频-11Stream之filter,distinct,skip,limit,map,flatmap详细介绍Java8实战视频-12Stream之Find,Match,Reduce详细介绍Java8实战视频-13NumericStream的详细介绍以及和Stream之间的相互转换Java8实战视频-14Stream综合练习,熟练掌握API的用法Java8实战视频-15在Optional出现之前经常遇到的空指针异常.wmvJava8实战视频-16Optional的介绍以及API的详解Java8实战视频-17Optional之flatMap,综合练习,Optional源码剖析Java8实战视频-18初识Collector体会Collector的强大Java8实战视频-19Collector使用方法深入详细介绍-01Java8实战视频-20Collector使用方法深入详细介绍-02Java8实战视频-21Collector使用方法深入详细介绍-03.wmvJava8实战视频-22Collector使用方法深入详细介绍-04Java8实战视频-23Collector原理讲解,JDK自带Collector源码深度剖析Java8实战视频-24自定义Collector,结合Stream的使用详细介绍Java8实战视频-25Parallel Stream编程体验,充分利用多核机器加快计算速度Java8实战视频-26Fork Join框架实例深入讲解Java8实战视频-27Spliterator接口源码剖析以及自定义Spliterator实现一个Stream.wmvJava8实战视频-28Default方法的介绍和简单的例子Java8实战视频-29Default方法解决多重继承冲突的三大原则详细介绍Java8实战视频-30多线程Future设计模式原理详细介绍,并且实现一个Future程序Java8实战视频-31JDK自带Future,Callable,ExecutorService介绍Java8实战视频-32实现一个异步基于事件回调的Future程序.wmvJava8实战视频-33CompletableFuture用法入门介绍Java8实战视频-34CompletableFuture之supplyAsync详细介绍Java8实战视频-35CompletableFuture流水线工作,join多个异步任务详细讲解Java8实战视频-36CompletableFuture常用API的重点详解-上Java8实战视频-37CompletableFuture常用API的重点详解-下Java8实战视频-38JDK老DateAPI存在的问题,新的DateAPI之LocalDate用法及其介绍.wmvJava8实战视频-39New Date API之LocalTime,LocalDateTime,Instant,Duration,Period详细介绍Java8实战视频-40New Date API之format和parse介绍

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值