1. 程式人生 > 程式設計 >java Socket 檔案伺服器(swing介面) 實現客戶端與伺服器的檔案傳輸

java Socket 檔案伺服器(swing介面) 實現客戶端與伺服器的檔案傳輸

前言

  • 基於Socket的TCP協議簡單實現客戶端和伺服器之間的檔案傳輸,實現上傳,下載檔案。

效果:

  • 客戶端:
    客戶端介面
  • 服務端:  

思路:

客戶端:

  • 開啟客戶端後,傳送讀取伺服器檔案列表訊息給伺服器,然後伺服器把檔案列表返回返回,然後客戶端再在介面上顯示即可。之後客戶端可進行下載,上傳檔案,重新整理檔案列表操作。所以客戶端這裡有三種型別訊息,為了能方便伺服器識別客戶端訊息的型別然後進行相應處理,簡單規範化雙方通訊協議。如下:然後要進行相應操作傳送相應訊息給伺服器即可。
通訊格式:
        1) 下載檔案訊息格式:@action=Download["fileName"
:"fileSize":"result"] 引數說明: fileName 要下載的檔案的名字 fileSize 要下載的檔案的大小 result 下載許可 2) 上傳檔案訊息格式: @action=Upload["fileName":"fileSize":result] 引數說明: fileName 要上傳的檔案的名字 * fileSize 要上傳的檔案的大小 result 上傳許可 3
)返回檔案列表格式 *; @action=GroupFileList["fileName1":"fileName2":"fileName3"...] 複製程式碼

服務端:

  • 服務端負責處理客戶端的各種訊息,比如請求下載訊息@action=Download["fileName":"fileSize":"result"],把客戶端請求下載的檔名解析出來,伺服器端判斷是否存在該檔案,並把結果按請求下載訊息把檔案大小和下載許可返回客戶端,若存在該檔案,然後伺服器開啟對客戶端的輸出流輸出檔案,客戶端接收到許可訊息後,開啟對伺服器的輸入流讀取檔案。

原始碼

伺服器程式碼

  • 一些檔案的儲存和讀取路徑目錄,需根據自己專案目錄結構更改
public class FileServer {
    private final int port = 5203;
    private ServerSocket server_socket;   //普通訊息傳輸伺服器套接字
    private ServerSocket fileServerSocket;  // 檔案傳輸伺服器套接字

    private String path ="檔案伺服器/GroupFile"; //伺服器檔案儲存路徑

    public FileServer() {
        try {
            //1-初始化
            server_socket = new ServerSocket(this.port);   // 建立訊息傳輸伺服器
            fileServerSocket = new ServerSocket(8888);  //建立檔案傳輸伺服器

              System.out.println("檔案伺服器啟動等待客戶端連線.....");
            //2-每次接收一個客戶端請求連線時都啟用一個執行緒處理
            while(true) {
                Socket client_socket = server_socket.accept();
                 System.out.println("客戶端:"+client_socket.getRemoteSocketAddress()+"已連線");
                new ServerThread(client_socket).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /** -----------------------------------------------------------------------------------------------------
     *
     *   啟用一個執行緒處理客戶端的請求
     */
    private class ServerThread extends Thread{
        private Socket client_socket;
        private BufferedReader server_in;
        private PrintWriter server_out;

        public ServerThread(Socket client_socket) {
            try {
                //初始化
                this.client_socket = client_socket;
                server_in = new BufferedReader(new InputStreamReader(this.client_socket.getInputStream()));
                server_out = new PrintWriter(this.client_socket.getOutputStream(),true);


            } catch (IOException e) {
            }
        }

        public void run() {
            try {
                String uploadFileName = null;
                String uploadFileSize = null;
                String fromClientData ;

                while((fromClientData = server_in.readLine()) != null){
                        //把伺服器檔案列表返回
                        if(fromClientData.startsWith("@action=loadFileList")){
                            File dir = new File(path);
                            if (dir.isDirectory()){
                                String[] list = dir.list();
                                String filelist = "@action=GroupFileList[";
                                for (int i = 0; i < list.length; i++) {
                                    if (i == list.length-1){
                                        filelist  = filelist + list[i]+"]";
                                    }else {
                                        filelist  = filelist + list[i]+":";
                                    }
                                }
                                server_out.println(filelist);
                            }
                        }

                        //請求上傳檔案
                        if (fromClientData.startsWith("@action=Upload")){
                            uploadFileName = ParseDataUtil.getUploadFileName(fromClientData);
                            uploadFileSize = ParseDataUtil.getUploadFileSize(fromClientData);
                            File file = new File(path,uploadFileName);
                            //檔案是否已存在
                            if (file.exists()){
                                //檔案已經存在無需上傳
                                server_out.println("@action=Upload[null:null:NO]");
                            }else {
                                //通知客戶端開可以上傳檔案
                                server_out.println("@action=Upload["+uploadFileName+":"+uploadFileSize+":YES]");
                                //開啟新執行緒上傳檔案
                                new HandleFileThread(1,uploadFileName,uploadFileSize).start();
                            }
                        }

                        //請求下載檔案
                        if(fromClientData.startsWith("@action=Download")){
                            String fileName = ParseDataUtil.getDownFileName(fromClientData);
                            File file = new File(path,fileName);
                            if(!file.exists()){
                                server_out.println("@action=Download[null:null:檔案不存在]");
                            }else {
                                //通知客戶端開可以下載檔案
                                server_out.println("@action=Download["+file.getName()+":"+file.length()+":OK]");
                                //開啟新執行緒處理下載檔案
                                new HandleFileThread(0,file.getName(),file.length()+"").start();
                                
                            }
                        }
                    }

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

        /**
         *     檔案傳輸執行緒
         */
        class HandleFileThread extends Thread{
            private String filename;
            private String filesize;
            private int mode;  //檔案傳輸模式

            public HandleFileThread(int mode,String name,String size){

                    filename = name;
                    filesize = size;
                    this.mode = mode;
            }

            public void run() {
                try {
                    Socket socket = fileServerSocket.accept();
                    //上傳檔案模式
                    if(mode == 1){
                        //開始接收上傳
                        BufferedInputStream file_in = new BufferedInputStream(socket.getInputStream());
                        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(path,filename)));

                        int len;
                        byte[] arr = new byte[8192];

                        while ((len = file_in.read(arr)) != -1){
                            bos.write(arr,0,len);
                            bos.flush();
                        }
                        server_out.println("@action=Upload[null:null:上傳完成]");
                        server_out.println("\n");
                        bos.close();
                    }

                    //下載檔案模式
                    if(mode == 0){
                       BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(path,filename)));
                       BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());

                       System.out.println("伺服器:開始下載");
                       int len;
                       byte[] arr =new byte[8192];
                       while((len = bis.read(arr)) != -1){
                           bos.write(arr,len);
                           bos.flush();
                       }

                       socket.shutdownOutput();
                    }
 					
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
	//啟動程式
    public static void main(String[] args) {
        new FileServer();
    }
}
複製程式碼

客戶端程式碼

  • 檔案列表顯示圖示fileIconPath自行提供設定,亦可刪除
public class GroupFileView extends JFrame {
    private int width = 400;
    private int height = 600;

    private JLabel groupLabel;
    private JButton uploadButton;
    private JLabel flushLabel;
    private String fileIconPath = "檔案客戶端/resource/file-min.png";
    private JScrollPane jScrollPane;
    private JPanel staffPanel;      //在JSpanel上的panel

    private Socket client_socket;
    private PrintStream client_out;
    private BufferedReader client_in;
    private String ip = "127.0.0.1";
    private int port = 5203;

    private File currentUpploadFile;
    private String downloadSavePath;
    private int Y = 0;


    public GroupFileView() {
        //1-初始化
        initVariable();
        //2-連線伺服器
        connectServer();
        //3-註冊監聽
        registerListener();
		//4-初始化視窗設定
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(width,height);
        this.setTitle("群檔案");
        this.setLocationRelativeTo(null);//視窗居中顯示
        this.setResizable(false);
        this.setVisible(true);
    }




    private void initVariable() {
        jScrollPane = new JScrollPane();
        this.getContentPane().add(jScrollPane);

        staffPanel = new JPanel();
        ///staffPanel.setLayout(new BoxLayout(staffPanel,BoxLayout.Y_AXIS));
        staffPanel.setLayout(null);
        staffPanel.setOpaque(false);
        staffPanel.setPreferredSize(new Dimension(width,height));

        jScrollPane.setViewportView(staffPanel);
        jScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);//設定水平滾動條隱藏
        jScrollPane.getViewport().setOpaque(false);  //設定透明
        jScrollPane.setOpaque(false);  //設定透明

        renderTop();
    }


    /**
     *      向伺服器重新讀取群檔案列表
     */
    private void loadGroupFile() {
            client_out.println("@action=loadFileList");
    }


    /**
     *   渲染頂部面板
     */
    private void renderTop(){
        staffPanel.removeAll();
        Y = 0;
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(1,3,10));
        this.groupLabel = new JLabel("\t\t\t\t\t群檔案列表 ");
        this.uploadButton = new JButton("上傳檔案 ");
        flushLabel = new JLabel(new ImageIcon("聊天室客戶端/resource/flush.png"));
        panel.add(groupLabel);
        panel.add(uploadButton);
        panel.add(flushLabel);

        panel.setBounds(2,Y,width,30);
        this.staffPanel.add(panel);
        Y += 30;
    }
    /**
         渲染檔案列表
     */
    public  void addToFileList(String filename){
        JLabel fileicon = new JLabel(new ImageIcon(fileIconPath));
        JButton downloadBtn = new JButton("下載");
        JLabel fileNameLab = new JLabel(filename);

        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(1,0));
        panel.add(fileicon);
        panel.add(fileNameLab);
        panel.add(downloadBtn);
        //panel.setBorder(BorderFactory.createLineBorder(Color.BLACK));

        panel.setBounds(2,30);
        this.staffPanel.add(panel);
        Y+=30;

        panel.addMouseListener(new MouseAdapter() {
            //滑鼠移入時
            public void mouseEntered(MouseEvent e) { // 滑鼠移動到這裡的事件
                panel.setBackground(Color.orange);
                panel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); // 讓滑鼠移動到
            }
            public void mouseExited(MouseEvent e) { // 滑鼠離開的事件
                panel.setBackground(Color.white);
            }

        });

        //檔案下載
        downloadBtn.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                 //1-選擇下載儲存的位置
                JFileChooser f = new JFileChooser(); // 查詢檔案
                f.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                f.showOpenDialog(null);
                File file = f.getSelectedFile();

                if(file != null){
                    downloadSavePath  = file.getPath();
                    //向伺服器請求下載
                    client_out.println("@action=Download["+filename+":null:null]");
                }
            }
        });
    }
    /**
     *   註冊監聽
     */
    private void registerListener() {
        //上傳檔案    訊息格式: @action=Upload["fileName":"fileSize":result]
        this.uploadButton.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                JFileChooser f = new JFileChooser(); // 查詢檔案
                f.showOpenDialog(null);
                currentUpploadFile = f.getSelectedFile();
                if(currentUpploadFile != null)
                client_out.println("@action=Upload["+currentUpploadFile.getName()+":"+currentUpploadFile.length()+":null]");

            }
        });

        //重新整理檔案列表按鈕
        flushLabel.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                loadGroupFile();
            }
            //滑鼠移入時
            public void mouseEntered(MouseEvent e) { // 滑鼠移動到這裡的事件
                flushLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); // 讓滑鼠移動到
            }
        });
    }

    /**
     *  連線伺服器
     */
    private void connectServer(){
        //連線伺服器
        try {
            //初始化
            client_socket = new Socket(ip,port);
            client_out = new PrintStream(client_socket.getOutputStream(),true);
            client_in = new BufferedReader(new InputStreamReader(client_socket.getInputStream()));

            //讀取檔案列表
            client_out.println("@action=loadFileList");

            //開啟執行緒監聽伺服器訊息
            new ClientThread().start();

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



    /**
     *    監聽伺服器訊息
     */
    class ClientThread extends Thread{
        public void run() {
            try {
                String fromServer_data;
                int flag = 0;

                while((fromServer_data=client_in.readLine()) != null){
                        //讀取群檔案列表
                        if(flag++ == 0){
                            if (fromServer_data.startsWith("@action=GroupFileList")){
                                String[] fileList = ParseDataUtil.getFileList(fromServer_data);
                                for (String filename : fileList) {
                                    addToFileList(filename);
                                }
                            }
                            continue;
                        }
                        if(fromServer_data.startsWith("@action=GroupFileList")){
                            //重新渲染頂部面板
                            renderTop();

                            //註冊監聽
                            registerListener();

                            //渲染檔案面板
                            String[] fileList = ParseDataUtil.getFileList(fromServer_data);
                            for (String filename : fileList) {
                                addToFileList(filename);
                            }

                        }

                        //檔案上傳
                        if (fromServer_data.startsWith("@action=Upload")){
                            String res = ParseDataUtil.getUploadResult(fromServer_data);
                            if("NO".equals(res)){
                                JOptionPane.showMessageDialog(null,"檔案已存在!");
                            }else if ("YES".equals(res)){
                                //開始上傳
                                if(currentUpploadFile != null){
                                    //開啟新執行緒傳輸檔案
                                    new HandelFileThread(1).start();
                                }

                            }else if ("上傳完成".equals(res)){
                                JOptionPane.showMessageDialog(null,res);
                                loadGroupFile();
                            }
                        }

                        //檔案下載
                        if(fromServer_data.startsWith("@action=Download")){
                            String res = ParseDataUtil.getDownResult(fromServer_data);
                            if(res.equals("檔案不存在")){
                                JOptionPane.showMessageDialog(null,"該檔案不存在404");
                            }else {
                                String downFileName = ParseDataUtil.getDownFileName(fromServer_data);
                                String downFileSize = ParseDataUtil.getDownFileSize(fromServer_data);
                                //開啟新執行緒傳輸檔案
                                new HandelFileThread(0,downFileName,downFileSize).start();
                            }
                        }
                    }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        /**----------------------------------------------------------------------------------
         *     檔案傳輸執行緒
         */
        class HandelFileThread extends Thread{
            private int mode;  //檔案傳輸模式  1-上傳  2-下載
            private String filename;
            private Long fileSize;

            public HandelFileThread(int mode) {
                this.mode = mode;
            }
            public HandelFileThread(int mode,String filename,String fileSize){
                this.mode = mode;
                this.filename = filename;
                this.fileSize = Long.parseLong(fileSize);
            }

            public void run() {
                try {
                    //上傳檔案模式
                    if(this.mode == 1){
                        Socket socket = new Socket(ip,8888);
                        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(currentUpploadFile));
                        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());

                        int len;
                        int i = 0;
                        double sum = 0;
                        byte[] arr = new byte[8192];
                        String schedule;

                        System.out.println("開始上傳--檔案大小為:"+currentUpploadFile.length());

                        while((len = bis.read(arr)) != -1){
                            bos.write(arr,len);
                            bos.flush();
                            sum += len;
                            if (i++ %100 == 0){
                                schedule = "上傳進度:"+100*sum/currentUpploadFile.length()+"%";
                                System.out.println(schedule);
                            }
                        }
                        //上傳完成
                        socket.shutdownOutput();
                        System.out.println("上傳進度:100%");
                    }

                    //下載檔案模式
                    if(this.mode == 0){
                        Socket socket = new Socket(ip,8888);
                        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
                        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(downloadSavePath+"/"+filename));

                        int len;
                        byte[] arr =new byte[8192];
                        double sumDown = 0;
                        int i = 0;

                        System.out.println("客戶端開始下載 ");
                        while ((len = bis.read(arr)) != -1){
                            sumDown += len;
                            if(i++%100 == 0)
                                System.out.println("下載進度為:"+100*sumDown/fileSize+"%");

                            bos.write(arr,len);
                            bos.flush();
                        }

                        bos.close();
                        bis.close();
                        socket.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
	//啟動程式
    public static void main(String[] args) throws Exception {
       new GroupFileView();
    }
複製程式碼

訊息解析工具:

public class ParseDataUtil {
 /**
     *
     * 下載檔案訊息格式: @action=Download["fileName":"fileSize":"result"]
     * 引數說明:
     *        fileName   要下載的檔案的名字
     *        fileSize   要下載的檔案的大小
              result     下載許可
     */
    public static String getDownFileName(String data){
        return data.substring(data.indexOf("[")+1,data.indexOf(":"));
    }
    public static String getDownFileSize(String data){
        return data.substring(data.indexOf(":")+1,data.lastIndexOf(":"));
    }
    public static String getDownResult(String data){
        return data.substring(data.lastIndexOf(":")+1,data.length()-1);
    }



    /**
     *
     *    上傳檔案訊息格式: @action=Upload["fileName":"fileSize":result]
          引數說明:
     *          fileName   要上傳的檔案的名字
     *          fileSize   要上傳的檔案的大小
                result     上傳許可
     */
    public static String getUploadFileName(String data){
        return data.substring(data.indexOf("[")+1,data.indexOf(":"));
    }
    public static String getUploadFileSize(String data){
        return data.substring(data.indexOf(":")+1,data.lastIndexOf(":"));
    }
    public static String getUploadResult(String data){
        return data.substring(data.lastIndexOf(":")+1,data.length()-1);
    }

    /**  返回檔案列表格式
     @action=GroupFileList["fileName":"fileName":"fileName"...]
     */
    public static String[] getFileList(String data){
        String list = data.substring(data.indexOf("[")+1,data.length()-1);
        return  list.split(":");
    }
}
複製程式碼

讚賞

                                                                                            

如果覺得文章有用,你可鼓勵下作者
如果浪費你時間了,在這裡先跟你抱歉