千家信息网

JAVA NIO服务器间连续发送文件(本地测试版)

发表于:2025-01-31 作者:千家信息网编辑
千家信息网最后更新 2025年01月31日,说在前面:给我的需求是实现从服务器A将大量文件(大概几十TB)发送到服务器B,在A服务器生成文件的MD5码,并在服务器B进行md5验证,验证通过保存。我的实现思路:将待上传的所有文件目录生成一个txt
千家信息网最后更新 2025年01月31日JAVA NIO服务器间连续发送文件(本地测试版)

说在前面:给我的需求是实现从服务器A将大量文件(大概几十TB)发送到服务器B,在A服务器生成文件的MD5码,并在服务器B进行md5验证,验证通过保存。

我的实现思路:

  • 将待上传的所有文件目录生成一个txt文件,格式如下。前缀中,当后面的数字等于9999的时候,前面的数字会自行相加。(此处加前缀的目的是为了整齐,而且失败了便于查询。)

AAA0000:D:\upload\addChannel.html

AAA0001:D:\upload\addChannel2.html

AAA0002:D:\upload\addContactPerson.html

AAA0003:D:\upload\admin.html

AAA0004:D:\upload\businessOfChannel.html

....

AAA9999:D:\upload\admin1.html

AAB0000:D:\upload\businessOfChannel1.html

...

  • 每次读取一条目录,进行上传。

  • 本地测试版未去实现的部分,没有把成功和失败的目录写到文件中,也没有添加日志。

2017/07/07增加部分

  • 添加部分注释

  • 添加对于大文件上传的解决方案

2017/07/12增加部分

  • 经过对代码的研究以及测试表明,2017/07/07修改的大文件上传有问题,问题出在bytebuffer的缓存有限制,byte.allocate(int)中的参数类型为int,即最大缓存为Integer.MAX_VALUE,即2^31-1的字节,大概是2G的大小。

  • 如果确定文件不会大于2G的话,用2017/07/07的部分应该足够,但是如果可以的话,依然推荐2017/07/12新增的部分代码

  • 新增的部分,不再原基础上进行修改,而是新增代码,只需要在客户端和服务器调用方法的时候,将handler.sendData(socketChannel, path, pathPre)改成handler.sendData2(socketChannel, path, pathPre),将this.handler.excute((ServerSocketChannel) s.channel())改成this.handler.excute2((ServerSocketChannel) s.channel())即可,当然在handler类中需要新增

    相应的方法(excute2(),receiveData2(),sendData2())

  • 另外添加RequestObject类,用于替代execute方法中的RequestObject2类,在execute方法中使用。

  • 在服务器端,原来是将接受到的文件先存到字节数组,然后对字节数组进行md5验证,但是字节数组的大小依然受到Integer.MAX_VALUE的限制。所以现在改成,直接将接收到的字节数组写入到文件,然后直接对文件进行MD5验证。这样excute2的方法会比之前逻辑有些变化。

  • 代码依然不够整洁,需要后续继续修改。


第一部分:将文件目录存储到文本中,文件夹不进行存储。

import java.io.File;import java.io.FileOutputStream;public class ReadAllPaths {        private static final String rootPath="D:/upload/"; //the root path of the files which will be copied         private static final String filePath="G:/temp/unUploadedFilePath.txt";//the record of all files path        /*         * the items of prefix and num construct the path prefix,for example AAA0001         * and it's mainly  convenient for searching         */        private String prefix="AAA";         private int num=0;        /**         * main         * @param args         * @throws Exception         */        public static void main(String[] args) throws Exception {                ReadAllPaths  paths=new ReadAllPaths();                File file=new File(filePath);                if(file.exists()){                        file.delete();                }                FileOutputStream out=new FileOutputStream(file,true);                paths.getAllPaths(rootPath, out);                out.close();        }                /**         * get all path out         * @param root         * @param out         * @throws Exception         */        private  void getAllPaths(String root,FileOutputStream out) throws Exception{                File file=new File(root);                                if(file.isDirectory()){                        try{if(file.list().length==0){                                return;                        }else{                                String[] files=file.list();                                for(String f:files){                                        getAllPaths(root+f+File.separator, out);                                }                        }                        }catch(NullPointerException npe){                                return;                        }                }else{                        String pathNum=getPathNum();                        String path=file.getAbsolutePath();                        out.write((pathNum+":"+path+"\n").getBytes());                }        }        /**         * get the path prefix         * @return         */        private String getPathNum(){                StringBuilder sb=new StringBuilder();                sb.append(getPrefix()).append(getNum());                setNum();                return sb.toString();        }                /**         * get the String prefix of path prefix         * @return         */        private String getPrefix() {                return prefix;        }        /**         * set the String prefix of path prefix         * for example:AAA AAB AAC....AAZ ABA....AZZ BAA...         */        private void setPrefix() {                char[] ch=new char[3];                ch=getPrefix().toCharArray();                if(ch[2]!='Z'){                        ch[2]++;                }else{                        ch[2]='A';                        if(ch[1]!='Z'){                                ch[1]++;                        }else{                                ch[1]='A';                                ch[0]++;                        }                }                prefix=new String(ch);        }        /**         * get the int prefix of path prefix         * @return         */        private String getNum() {                StringBuffer sb=new StringBuffer();                if(num<10){                        sb.append("000").append(num);                }else if(num<100){                        sb.append("00").append(num);                }else if(num<1000){                        sb.append("0").append(num);                }else{                        sb.append(num);                }                return sb.toString();        }        /**         * set the int prefix of path prefix         * and the max num is 9999 and the min is 0000         */        private void setNum() {                if(num<9999){                                                num++;                }else{                        num=0;                        setPrefix();                }        }}

第二部分,服务器端代码

import java.io.IOException;import java.net.InetSocketAddress;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.util.Iterator;public class Server {        Selector selector = null;        ServerSocketChannel serverSocketChannel = null;        private NioserverHandler2 handler;        public Server() throws IOException {                selector = Selector.open();                // 打开服务器套接字通道                serverSocketChannel = ServerSocketChannel.open();                // 调整通道的阻塞模式非阻塞                serverSocketChannel.configureBlocking(false);                //serverSocketChannel.socket().setReuseAddress(true);这里没明白有什么用,//所以注释了                serverSocketChannel.socket().bind(new InetSocketAddress(9999));                    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);        }        public Server(NioserverHandler2 handler) throws IOException {                this();                this.handler = handler;                while (selector.select() > 0) {                        Iterator it = selector.selectedKeys().iterator();                        while (it.hasNext()) {                                SelectionKey s = it.next();                                it.remove();                                this.handler.excute((ServerSocketChannel) s.channel());                        }                }        }        public static void main(String[] args) throws IOException {                new Server(new NioserverHandler2());        }}public class NioserverHandler2 {        //2017/07/07增加注释        /*该目录用于服务端文件的存储。        */        private final static String DIRECTORY = "G:\\NioRequest\\";        /*        *2017/07/07增加        *用于存储上传文件成功失败情况的目录,        *成功的放在succeed.log中        *格式为客户端传过来的带前缀的路径,无特殊格式,每个一行        *失败的放在failed.log中        *格式为reason+带前缀路径        */        private final static String ResultPath = "G:\\serverLog\\";        /*        *2017/07/07修改        *新增构造方法,检测succeed.log,failed.log以及其目录是否存在,不存在则创建        */        public NioserverHandler2() {                File file = new File(ResultPath);                File file1 = new File(ResultPath + "succeed.log");                File file2 = new File(ResultPath + "failed.log");                if (!file.exists()) {                        file.mkdirs();                }                if (!file1.exists()) {                        try {                                file1.createNewFile();                        } catch (IOException e) {                                e.printStackTrace();                        }                }                if (!file2.exists()) {                        try {                                file2.createNewFile();                        } catch (IOException e) {                                e.printStackTrace();                        }                }        }        /**         * 这里边我们处理接收和发送         *          * @param serverSocketChannel         */        public void excute(ServerSocketChannel serverSocketChannel) {                SocketChannel socketChannel = null;                /*                *2017/07/07增加该字段                *自己测试中发现,有些文件可以读写执行,但是却无法正确发送                *所以在client发送的fileInfo中新增了一个字段,如果把文件读取到字节数组失败                *则设置字节数组为空                *此时字节数组为空有两种情况:                *文件为0KB大小,还有上面的一种情况,                *前者需要直接新建一个空文件,后者需要报错                *所以client端新增一个字段,用于区分这两种情况。                *第一种情况是fileInfo中设置一个well字符串                *第二种情况是fileInfo中设置一个error字符串                *                *此处新增的status由于区分不同情况                *status==0 文件传送正确,并且MD5验证通过                *status==1 文件传送正确,但是MD5验证未通过                *status==2 文件传输失败                *以后如果有新的错误,会在这里继续追加状态                */                int status=0;                try {                        socketChannel = serverSocketChannel.accept(); // 等待客户端连接                        RequestObject2 requestObject = receiveData(socketChannel);// 接数据                                                //md5验证,用的是apache的,2017/07/07添加注释                        String md5 = DigestUtils.md5Hex(requestObject.getContents());                        //用于对客户端的相应,其实在本程序中用处不太大                        String response = "";                        //2017/07/07添加该字段,用于判断成功失败                            boolean flag=true;                        /*                        *2017/07/07对于判断进行修改,新增了判断status字段是否为error                        *至于下面的responseObject不用关于,只是为了方便固定格式的字符串而已                        */                        if(requestObject.getStatus().equals("error")){                                flag=false;                                status=2;                                response = (new ResponseObject("failed", requestObject.getAbsolutePath(), "fail error")).toString();                        }else{                                if (md5.equals(requestObject.getMd5())) {                                        response = (new ResponseObject("succeed", requestObject.getAbsolutePath(), "")).toString();                                        File file = new File(DIRECTORY + requestObject.getRelativePath());                                        if (!file.exists()) {                                                file.mkdirs();                                        }                                        File file1 = new File(DIRECTORY + requestObject.getRelativePath() + requestObject.getFilename());                                        if (!file1.exists()) {                                                file1.createNewFile();                                        }                                        FileOutputStream fos = new FileOutputStream(file1);                                        fos.write(requestObject.getContents());                                        fos.close();                                } else {                                        flag=false;                                        status=1;                                        response = (new ResponseObject("failed", requestObject.getAbsolutePath(), "md5验证失败")).toString();                                }                        }                        //将处理结果写入到succeed.log和failed.log中                        writeRusultToFile(flag, requestObject.getAbsolutePath(),status);                        //响应客户端                        responseData(socketChannel, response);                } catch (IOException e) {                        e.printStackTrace();                }        }                /*        *2017/07/12新增代码        *md5验证方式从验证字节数组改成验证文件流。        *将之前写入文件的部分代码删除,因为在receiveData2已经将文件进行了写入。        *        */        public void excute2(ServerSocketChannel serverSocketChannel) {                SocketChannel socketChannel = null;                int status=0;                try {                        socketChannel = serverSocketChannel.accept(); // 等待客户端连接                        RequestObject requestObject = receiveData2(socketChannel);// 接数据                        String md5 = DigestUtils.md5Hex(new FileInputStream(new File(DIRECTORY+requestObject.getRelativePath()+requestObject.getFilename())));                        System.out.println(md5);                        String response = "";                        boolean flag = true;                        if(requestObject.getStatus().equals("error")){                                flag=false;                                status=2;                                response = (new ResponseObject("failed", requestObject.getAbsolutePath(), "fail error")).toString();                        }else{                                if (md5.equals(requestObject.getMd5())) {                                        response = (new ResponseObject("succeed", requestObject.getAbsolutePath(), "")).toString();                                } else {                                        flag=false;                                        status=1;                                        response = (new ResponseObject("failed", requestObject.getAbsolutePath(), "md5验证失败")).toString();                                }                        }                        writeRusultToFile(flag, requestObject.getAbsolutePath(),status);                        System.out.println(response);                        responseData(socketChannel, response);                } catch (IOException e) {                        e.printStackTrace();                }        }        /**         * 

* 读取通道中的数据到Object里去 *

* * @param socketChannel * @return * @throws IOException */ public RequestObject2 receiveData(SocketChannel socketChannel) throws IOException { // 文件名 String fileName = null; String relativePath = null; String absolutePath = null; String md5 = null; //2017/07/07新增字段,因为RequestObject2字段进行了修改,所以添加 String status=null; // 文件长度 int contentLength = 0; // 文件内容 byte[] contents = null; // 由于我们解析时前4个字节是文件名长度 int capacity = 4; ByteBuffer buf = ByteBuffer.allocate(capacity); int size = 0; byte[] bytes = null; // 拿到文件名的长度 size = socketChannel.read(buf); if (size >= 0) { buf.flip(); capacity = buf.getInt(); buf.clear(); } buf = ByteBuffer.allocate(capacity); size = socketChannel.read(buf); if (size >= 0) { buf.flip(); bytes = new byte[size]; buf.get(bytes); buf.clear(); } String fileInfo = new String(bytes); System.out.println(fileInfo); /*2017/07/07增加注释,并添加字段 *并进行部分修改 */ status=fileInfo.split(";")[0]; fileName = fileInfo.split(";")[1]; relativePath = fileInfo.split(";")[2]; absolutePath = fileInfo.split(";")[3]; md5 = fileInfo.split(";")[4]; // 拿到文件长度 capacity = 4; buf = ByteBuffer.allocate(capacity); size = socketChannel.read(buf); if (size >= 0) { buf.flip(); // 文件长度是可要可不要的,如果你要做校验可以留下 capacity = buf.getInt(); buf.clear(); } if (capacity == 0) { contents = new byte[] {}; } else { // 用于接收buffer中的字节数组 ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 文件可能会很大 // capacity = 1024; buf = ByteBuffer.allocate(capacity); while ((size = socketChannel.read(buf)) >= 0) { buf.flip(); bytes = new byte[size]; buf.get(bytes); baos.write(bytes); buf.clear(); } contents = baos.toByteArray(); } RequestObject2 requestObject = new RequestObject2(fileName, relativePath, absolutePath, md5, contents,status); return requestObject; } private void responseData(SocketChannel socketChannel, String response) { ByteBuffer buffer = ByteBuffer.wrap(response.getBytes()); try { socketChannel.write(buffer); buffer.clear(); // 确认要发送的东西发送完了关闭output 不然它端接收时socketChannel.read(Buffer) // 很可能造成阻塞 ,可以把这个(L)注释掉,会发现客户端一直等待接收数据 socketChannel.socket().shutdownOutput();// (L) } catch (IOException e) { e.printStackTrace(); } } /* *2017/07/12新增方法,用于excute2()方法 *大部分代码和2017/07/07的代码相似,因为客户端发送的文件大小可能超出int类型,所以改成long类型,所以服务端也自然进行了修改 *因为可能文件过大,所以直接将接收到的字节数组写入到文件中。 *这里的注释可能比较少 */ public RequestObject receiveData2(SocketChannel socketChannel) throws IOException { String status=null; String fileName = null; String relativePath = null; String absolutePath = null; String md5 = null; int contentLength = 0; // 由于我们解析时前4个字节是文件名长度 int capacity = 4; ByteBuffer buf = ByteBuffer.allocate(capacity); int size = 0; byte[] bytes = null; // 拿到文件名的长度 size = socketChannel.read(buf); if (size >= 0) { buf.flip(); capacity = buf.getInt(); buf.clear(); } buf = ByteBuffer.allocate(capacity); size = socketChannel.read(buf); if (size >= 0) { buf.flip(); bytes = new byte[size]; buf.get(bytes); buf.clear(); } status = fileInfo.split(";")[0]; fileName = fileInfo.split(";")[1]; relativePath = fileInfo.split(";")[2]; absolutePath = fileInfo.split(";")[3]; md5 = fileInfo.split(";")[4]; // 拿到文件长度,因为long类型占8个字节,所以这里为8 capacity = 8; buf = ByteBuffer.allocate(capacity); size = socketChannel.read(buf); long cap=0; if (size >= 0) { buf.flip(); // 文件长度显得不那么重要了 cap = buf.getLong(); buf.clear(); } System.out.println(cap); if (status.equals("well")) { File file = new File(DIRECTORY + relativePath); if (!file.exists()) { file.mkdirs(); } File file1 = new File(DIRECTORY + relativePath + fileName); if (!file1.exists()) { file1.createNewFile(); } FileOutputStream fos=new FileOutputStream(file1); //每次接受1KB的字节数组,可以根据需要自己修改。注意有Integet.MAXVALUE的限制。 buf = ByteBuffer.allocate(1024); while ((size = socketChannel.read(buf)) >= 0) { buf.flip(); bytes = new byte[size]; buf.get(bytes); fos.write(bytes); buf.clear(); } fos.close(); } RequestObject requestObject = new RequestObject(fileName, relativePath, absolutePath, md5,status); return requestObject; }}import java.io.Serializable;public class RequestObject2 implements Serializable { private static final long serialVersionUID = 1L; private String filename; private String relativePath; private String absolutePath; private String md5; private byte[] contents; private String status; public RequestObject2(String filename, String relativePath, String absolutePath, String md5, byte[] contents,String status) { this.filename = filename; this.relativePath = relativePath; this.absolutePath = absolutePath; this.md5 = md5; this.contents = contents; this.status=status; } public String getFilename() { return filename; } public String getRelativePath() { return relativePath; } public String getAbsolutePath() { return absolutePath; } public String getMd5() { return md5; } public byte[] getContents() { return contents; } public String getStatus(){ return status; }}/**2017/07/12新增类,用于excute2方法*想对于RequestObject,删除了byte[]*/import java.io.Serializable;public class RequestObject implements Serializable { private static final long serialVersionUID = 1L; private String filename; private String relativePath; private String absolutePath; private String md5; private String status; public RequestObject(String filename, String relativePath, String absolutePath, String md5, String status) { this.filename = filename; this.relativePath = relativePath; this.absolutePath = absolutePath; this.md5 = md5; this.status = status; } public String getFilename() { return filename; } public String getRelativePath() { return relativePath; } public String getAbsolutePath() { return absolutePath; } public String getMd5() { return md5; } public String getStatus() { return status; }}

第三部分 客户端代码

import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.IOException;import java.net.InetSocketAddress;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;public class Client2 {        /*        *2017/07/07添加该注释        *用于存储要被上传文件的目录,即文章第一部分代码生成文件的位置        */        private static final String unpath = "G:\\temp\\unUploadedFilePath.txt";        /*        *2017/07/07添加该注释        *待上传文件所在的目录        *还有一个作用,用于获得相对路径        */        private static final String pathPre = "D:\\upload\\";        //2017/07/07添加该注释        //服务器地址,因为是本地测试,所以用这个        private static final String IPADDR = "127.0.0.1";        //2017/07/07添加该注释        //服务端口号        private static final int PORT = 9999;        Selector selector;        public Client2() throws IOException {                selector = Selector.open();                new Thread(new SendDataRunnable()).start();        }        private class SendDataRunnable implements Runnable {                private ClientHandler handler;                public SendDataRunnable() {                        handler = new ClientHandler();                }                @Override                public void run() {                        try {                                BufferedReader reader = new BufferedReader(new FileReader(new File(unpath)));                                String path = "";                                while ((path = reader.readLine()) != null && path.length() != 0) {                                        SocketChannel socketChannel;                                        socketChannel = SocketChannel.open();                                        socketChannel.connect(new InetSocketAddress(IPADDR, PORT));                                        socketChannel.configureBlocking(false);                                        socketChannel.register(selector, SelectionKey.OP_READ);                                        handler.sendData(socketChannel, path, pathPre);                                        String response = handler.receiveData(socketChannel);                                        System.out.println(response);                                        socketChannel.close();                                }                        } catch (Exception e) {                                e.printStackTrace();                        }                }        }        public static void main(String[] args) throws IOException {                Client2 client = new Client2();        }}import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.nio.ByteBuffer;import java.nio.channels.SocketChannel;import org.apache.commons.codec.digest.DigestUtils;public class ClientHandler {                public void sendData(SocketChannel socketChannel,String path,String pathPre)throws Exception{                        System.out.println(path);                        String absoluteFilePath=getAbsoluteFilePath(path);                        String fileName=getFileName(absoluteFilePath);                        String relativeFilePath=getRelativeFilePath(absoluteFilePath, pathPre,fileName);                        System.out.println(absoluteFilePath);                        /*                        *2017/07/07添加该字段                        *用于区分文件是否正确读取                        */                        String status="well";                        byte[] bytes=makeFileToBytes(absoluteFilePath);                        System.out.println(bytes.length);                        String md5=DigestUtils.md5Hex(bytes);                        /*                        *2017/07/07添加该注释                        *进行部分修改,增加status部分                        */                        String fileInfo=new StringBuffer()                                        .append(status)                                        .append(";")                                        .append(fileName)                                        .append(";")                                        .append(relativeFilePath)                                        .append(";")                                        .append(path)                                        .append(";")                                        .append(md5)                                        .toString();                        System.out.println(fileInfo);                        ByteBuffer buffer = ByteBuffer.allocate(8 +fileInfo.getBytes().length+bytes.length);                        buffer.putInt(fileInfo.getBytes().length);                        buffer.put(fileInfo.getBytes());                        buffer.putInt(bytes.length);                        buffer.put(ByteBuffer.wrap(bytes));                        buffer.flip();                        /*                        *2017/07/07进行修改                        *之前没有外面的while循环,发现大文件server端一直接收失败                        *所以进行的添加。                        */                        while (buffer.hasRemaining()) {                                socketChannel.write(buffer);                        }                        buffer.clear();                // 关闭输出流防止接受时阻塞,就是告诉接收方本次的内容已经发完了,你不用等了                socketChannel.socket().shutdownOutput();        }        /*        *2017/07/12新增代码        */                        public void sendData2(SocketChannel socketChannel, String path, String pathPre) {                System.out.println(path);                String absoluteFilePath = getAbsoluteFilePath(path);                File file = new File(absoluteFilePath);                String fileName = getFileName(absoluteFilePath);                String relativeFilePath = getRelativeFilePath(absoluteFilePath, pathPre, fileName);                System.out.println(absoluteFilePath);                String status = "well";                String md5 = null;                int bufferSize = 1024;//用于每次发送文件的大小设置,可以自行修改                try {                        RandomAccessFile rafi = new RandomAccessFile(absoluteFilePath, "r");                        byte[] buf = new byte[bufferSize];                        int c = 0;                        try {                                c = rafi.read(buf);                                FileInputStream fis = new FileInputStream(new File(absoluteFilePath));                                md5 = DigestUtils.md5Hex(fis);                                fis.close();                        } catch (Exception e) {                                c = 0;                                status = "error";                                md5 = "0";                        }                        String fileInfo = new StringBuffer().append(status).append(";").append(fileName).append(";")                                        .append(relativeFilePath).append(";").append(path).append(";").append(md5).toString();                        System.out.println(fileInfo);                        int len = c;                        //这里注意下12,因为之前是发送两个int类型,所以是8,现在是一个int一个long,所以12                        ByteBuffer buffer = ByteBuffer.allocate((int) (12 + fileInfo.getBytes().length + bufferSize));                        buffer.putInt(fileInfo.getBytes().length);                        buffer.put(fileInfo.getBytes());                        buffer.putLong(len > 0 ? file.length() : 0);                        /*                        *说下flag的作用                        *flag==true 表示这次发送的是一个buffersize的大小,可能后续还有字节数组没发送完成,需要继续判断;另外当c==0的时候,true的作用是用于后面发送文件的基本信息。                        *flag==false表示这次发送的不是一个buffersize的大小,也表示已经发送完成,无需后续判断                        */                        boolean flag = true;                        while(c>0){                                        if (c == buf.length) {                                                buffer.put(ByteBuffer.wrap(buf));                                                flag = true;                                        } else {                                                buffer.put(ByteBuffer.wrap(buf, 0, c));                                                c = 0;                                                flag = false;                                        }                                        buffer.flip();                                        while (buffer.hasRemaining()) {                                                socketChannel.write(buffer);                                        }                                        if(flag) {                                                buffer.clear();                                                c = rafi.read(buf);                                        }                        }                        if(flag){                                buffer.flip();                                while (buffer.hasRemaining()) {                                        socketChannel.write(buffer);                                }                        }                        rafi.close();                        buffer.clear();                        // 关闭输出流防止接受时阻塞,就是告诉接收方本次的内容已经发完了,你不用等了                        socketChannel.socket().shutdownOutput();                } catch (Exception e) {                        e.printStackTrace();                                        }        }                                        /*        *2017/07/07添加注释        *用于从类似AAA0000:D:\upload\addChannel.html格式的目录中读取真正的文件目录        */        private String getAbsoluteFilePath(String path){                return path.substring(8);        }        /*        *2017/07/07添加注释        *用于从类似D:\upload\addChannel.html格式的目录中拿到被存储的相对路径(说的啥啊,自己都看不懂)        *举个例子:        *客户端文件目录D:\upload\test1\test2\addChannel.html,即为下面的absoluteFilePath        *我想存储到服务器的 G:\NioRequest\test1\test2\addChannel.html        *所以我要获得客户端目录的test1\test2\addChannel.html部分        *然后拼接到服务器的目录G:\NioRequest\目录上        *下面的pathPre是为前缀,上面例子中就是D:\upload\        *因为我要的目录中不包括文件名,所以加了个文件名字段        */        private String getRelativeFilePath(String absoluteFilePath,String pathPre,String fileName){                return absoluteFilePath.substring(pathPre.length(),absoluteFilePath.length()-fileName.length());        }        /*        *2017/07/07添加注释        *这个太简单,不解释        */        private String getFileName(String path){                return new File(path).getName();        }                /*        *2017/07/07添加注释        *将文件读取到字节数组,不是我自己写的,网上找到的        */                private byte[] makeFileToBytes(String filePath){                File file=new File(filePath);                byte[] ret = null;          try {                FileInputStream in = new FileInputStream(file);              ByteArrayOutputStream out = new ByteArrayOutputStream(4096);              byte[] b = new byte[4096];              int n;              while ((n = in.read(b)) != -1) {                  out.write(b, 0, n);              }              in.close();              out.close();              ret = out.toByteArray();          } catch (IOException e) {              // log.error("helper:get bytes from file process error!");              e.printStackTrace();          }          return ret;          }                public String receiveData(SocketChannel socketChannel) throws IOException {                ByteArrayOutputStream baos = new ByteArrayOutputStream();                String response = "";                try {                        ByteBuffer buffer = ByteBuffer.allocate(1024);                        byte[] bytes;                        int count = 0;                        while ((count = socketChannel.read(buffer)) >= 0) {                                buffer.flip();                                bytes = new byte[count];                                buffer.get(bytes);                                baos.write(bytes);                                buffer.clear();                        }                        bytes = baos.toByteArray();                        response = new String(bytes, "UTF-8");//                      socketChannel.socket().shutdownInput();                } finally {                        try {                                baos.close();                        } catch (Exception ex) {                        }                }                return response;        }}

/*至此全部完成,注释不够多,部分代码是从网上找的。后期有时间会补全注释的,或者下次直接上最终使用的代码*/

0