java Socket 檔案伺服器(swing介面) 實現客戶端與伺服器的檔案傳輸
阿新 • • 發佈:2019-12-31
前言
- 基於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(":");
}
}
複製程式碼
讚賞