ChatAPP --- 好友间发送文件

一,简介
通过socket的tcp/ip协议,发送文件


二,原理
发送端:发送文件,先发送文件类型和文件名字---再进行发送文件
接收端:先判断是否是文件传输,是就进行文件名的获取-----并创建文件,把文件流逐一写入文件。


三,代码
发送端

/**
     * 发送文件
     */
    @OnClick(R.id.sendfile)
    public void sendFile(){

        final String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/ab.doc";
        send_str = new File(path).getName();
        if (!send_str.isEmpty()){
            Chat chat = new Chat();
            chat.setId(1);
            chat.setTalk(send_str);
            chat.setFiletype(getString(R.string.file));
            chats.add(chat);
            chatAdapter.notifyDataSetChanged();
            //自动滑到最底端
            mRecycle.scrollToPosition(chatAdapter.getItemCount()-1);
            Thread thread = new Thread(){
                @Override
                public void run() {
                    super.run();

                    try {
                        sockets = new Socket(ip_diu,8000);

                        outputStream = sockets.getOutputStream();

                        byte[] buffer = TalkUtil.CreateJson(getString(R.string.file) , send_str);
                        outputStream.write(buffer);
                        SendFileUtil.sendFiel(sockets , outputStream , path);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }


                }
            };
            thread.start();
        }else {
            Toast.makeText(this,R.string.send_select , Toast.LENGTH_SHORT).show();
        }


    }
/**
     * 发送文件
     * @param path 文件地址
     */
    public static void sendFiel(Socket s , OutputStream out, String path) {
        try {

            FileInputStream inputStream = new FileInputStream(new File(path));
            byte[] buf = new byte[1024];
            int len;
            //判断是否读到文件末尾
            while ((len = inputStream.read(buf)) != -1) {
                out.write(buf, 0, len);//将文件循环写入输出流
            }
            //告诉服务端,文件已传输完毕
            s.shutdownOutput();
            //获取从服务端反馈的信息
            /*BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
            String serverBack = in.readLine();
            Log.d("TAG", serverBack);*/
            //资源关闭
            s.close();
            inputStream.close();

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

接收端

  /*
  服务器端接收数据
  需要注意以下一点:
  服务器端应该是多线程的,因为一个服务器可能会有多个客户端连接在服务器上;
  */
    private void receiveData() {
        Thread thread = new Thread(){
            @Override
            public void run() {
                super.run();
                /*
                指明端口号
                 */
                try {
                    serverSocket = new ServerSocket(8000);
                }catch (IOException e){
                    e.printStackTrace();
                }
                /*
                循环启动服务
                 */
                boolean b = true;
                while (b){
                    Socket socket = null;
                    try {
                        if (!serverSocket.isClosed()){
                            socket = serverSocket.accept();
                            inputStream = socket.getInputStream();
                            new ServerThread(socket,inputStream).start();
                        }else {
                            b = false;
                            socket.close();
                            return;
                        }

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

                }

            }
        };
        thread.start();
    }

    class ServerThread extends Thread{

        private Socket socket;
        private InputStream inputStream;


        public ServerThread(Socket socket,InputStream inputStream){
            this.socket = socket;
            this.inputStream = inputStream;
        }

        @Override
        public void run() {
            try {

                int len = getxmlLeng(inputStream);
                byte[] buffer = toByteArraytolong(inputStream , len);
                String json_str =  new String(buffer, "UTF-8");
                try {
                    JSONObject jsonObject = new JSONObject(json_str);
                    String type = jsonObject.getString(Constant.type_key);
                    if (type.equals(getString(R.string.file))){
                        String filename = jsonObject.getString(Constant.talk_key);
                        AcceptFileUtil.receiveFile(getContext() , filename , inputStream );
                    }
                    Intent intent = new Intent(Constant.BROAD_REVICE);
                    intent.putExtra("msg",json_str);
                    sendBroadcast(intent);

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

                //当这个异常发生时,说明客户端那边的连接已经断开

            } catch (IOException e) {
                e.printStackTrace();
                try {
                    inputStream.close();
                    socket.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }

            }

        }
    }
    /**将输入流转化成byte[]的方法
     * */
    public static byte[] toByteArraytolong(InputStream input , int len) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();

        byte[] buffer = new byte[4096];
        int n = 0;
        while ((n = input.read(buffer, 0, buffer.length)) != -1) {
            output.write(buffer, 0, n);
            int leng =  output.toByteArray().length;
            if ( leng >= len){
                break;
            }
        }
        return output.toByteArray();
    }

    /**
     * 包头解析
     */
    private static int getxmlLeng(InputStream in)throws IOException{
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[4];
        int n = in.read(buffer);
        output.write(buffer, 0, n);

        byte[] b = output.toByteArray();
        int len = b[0] & 0xFF |
                (b[1] & 0xFF) << 8 |
                (b[2] & 0xFF) << 16 |
                (b[3] & 0xFF) << 24;
        return len;


    }
/**in
     * 接收文件
     * FileName 文件名字
     */
    public static synchronized void receiveFile(Context context , String FileName ,InputStream in ) {
        boolean b = true;
        try {
            while (b) {

                //创建一个文件,指定保存路径和刚才传输过来的文件名
                OutputStream saveFile = new FileOutputStream(
                        new File(context.getExternalCacheDir(), FileName));
                byte[] buf = new byte[1024];
                int len;
                //判断是否读到文件末尾
                while ((len = in.read(buf)) != -1) {
                    saveFile.write(buf, 0, len);
                }
                saveFile.flush();
                saveFile.close();
                //告诉发送端我已经接收完毕
                /*OutputStream outputStream = socket.getOutputStream();
                outputStream.write("文件接收成功".getBytes());
                outputStream.flush();
                outputStream.close();
                socket.close();*/
                b = false;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

猜你喜欢

转载自blog.csdn.net/qwer492915298/article/details/88555742