通过Socket实现文件上传/上传文件
文章目錄
- 整個功能的實現步驟
- 客戶端的實現步驟
- 服務端的實現步驟
- 示例代碼
整個功能的實現步驟
1.客戶端使用本地的字節輸入流讀取被上傳的文件數據
2.客戶端使用網絡字節輸出流,將讀取到的文件數據發送給服務端
3.服務端使用網絡字節輸入流讀取客戶端發送過來的文件數據
4.服務端使用本地字節輸出流將讀取到的文件數據寫入到指定的服務器本地文件中(例如,保存到目錄 upload 下面)
5.服務端使用網絡字節輸出流,給客戶端回寫一段文字:“上傳成功”
6.客戶端使用網絡字節輸入流,讀取服務端返回的數據
7.釋放資源
注意:
1.客戶端和服務端對本地硬盤進行讀寫,需要使用自己創建的 IO 流,稱為本地流
2.客戶端和服務端之間進行數據讀寫,必須使用 Socket 中提供的 IO 流,稱為網絡流
客戶端的實現步驟
1.創建一個本地字節輸入流對象(即 FileInputStream),構造方法中綁定要讀取的數據源
2.創建一個客戶端對象(即 Socket 對象),構造方法中綁定 IP 和端口號
3.使用 Socket 對象的方法 getOutputStream,獲取網絡字節輸出流對象
4.使用 FileInputStream 對象的方法 read 讀取要上傳的文件數據
5.使用網絡字節輸出流對象的方法 write,將讀取到的文件數據發送到服務端
6.使用 Socket 對象的方法 getInputStream 獲取網絡字節輸入流對象
7.使用網絡字節輸入流對象的方法 read 讀取服務端回寫的數據
8.釋放資源(FileInputStream、Socket)
服務端的實現步驟
1.創建一個服務端對象(即 ServerSocket),并且向系統要指定的端口號
2.使用服務端對象的方法 accept 獲取請求的客戶端對象(即請求連接的 Socket 對象)
3.使用 Socket 對象的方法 getInputStream 獲取網絡字節輸入流
4.判斷服務端的目標目錄路徑是否存在,若不存在要創建此目錄
5.創建一個本地字節輸出流對象(即 FileOutputStream),構造方法中要綁定寫入數據的目標文件路徑
6.使用網絡字節輸入流的方法 read 讀取客戶端發送過來的文件數據
7.使用 FileOutputStream 對象的方法 write 將讀取到文件數據寫入到服務器本地文件中
8.使用 Socket 對象的方法 getOutputStream 獲取網絡字節輸出流對象
9.使用網絡字節輸出流對象的方法 write 給客戶端發送一段文字:文件上傳成功!
10.釋放資源(FileOutputStream、Socket、ServerSocket)
示例代碼
客戶端代碼:
package priv.lwx.javaex.fileupload;import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket;/*** @ClassName TCPClient* @Description 客戶端讀取本地的文件數據,發送給服務端* @Author liaowenxiong* @Version 1.0* @date 2021/9/5 下午4:50*/ public class TCPClient {public static void main(String[] args) throws IOException {// 1.創建一個本地字節輸入流對象(即 `FileInputStream`),構造方法中綁定要讀取的數據源FileInputStream fis = new FileInputStream("/Users/liaowenxiong/desktop/test/1.jpeg");// 2.創建一個客戶端對象(即 Socket 對象),構造方法中綁定 IP 和端口號Socket socket = new Socket("127.0.0.1", 8888);// 3.使用 Socket 對象的方法 getOutputStream,獲取網絡字節輸出流對象OutputStream os = socket.getOutputStream();// 4.使用 FileInputStream 對象的方法 read 讀取要上傳的文件數據byte[] bytes = new byte[1024];int i = 0;while ((i = fis.read(bytes)) != -1) {// 5.使用網絡字節輸出流對象的方法 write,將讀取到的文件數據發送到服務端os.write(bytes, 0, i); // i表示獲取數組元素的個數}// 禁用此套接字的輸出流,此時會寫入一個終止標記,這樣服務端就可以讀取到此標記,就不會出現阻塞的問題了// 終止標記表示輸出流寫出的數據已經沒有了,服務端解析到這個標記后就,有關的線程就不會一直處于等待接收// 數據的狀態socket.shutdownOutput();// 6.使用 Socket 對象的方法 getInputStream 獲取網絡字節輸入流對象InputStream is = socket.getInputStream();// 7.使用網絡字節輸入流對象的方法 read 讀取服務端回寫的數據到指定的字節數組中i = is.read(bytes);// 讀取幾個字節,就返回幾// 將字節數組中的數據轉換成字符串,并打印到控制臺System.out.println(new String(bytes, 0, i));// 8.釋放資源(FileInputStream、Socket)fis.close();socket.close();} }服務端代碼:
package priv.lwx.javaex.fileupload;import java.io.*; import java.net.ServerSocket; import java.net.Socket;/*** @ClassName TCPServer* @Description 服務端讀取客戶端發送過來的文件數據,并寫入到指定的服務器本地的文件中* @Author liaowenxiong* @Version 1.0* @date 2021/9/5 下午7:38*/ public class TCPServer {public static void main(String[] args) throws IOException {// 1.創建一個服務端對象(即 ServerSocket),并且向系統要指定的端口號ServerSocket server = new ServerSocket(8888);// 2.使用服務端對象的方法 accept 獲取請求的客戶端對象(即請求連接的 Socket 對象)Socket socket = server.accept();// 3.使用 Socket 對象的方法 getInputStream 獲取網絡字節輸入流InputStream is = socket.getInputStream();// 4.判斷服務端的目標目錄路徑是否存在,若不存在要創建此目錄File file = new File("/Users/liaowenxiong/desktop/test/upload");if (!file.exists()) {file.mkdirs();}// 5.創建一個本地字節輸出流對象(即 FileOutputStream),構造方法中要綁定寫入數據的目標文件路徑FileOutputStream fos = new FileOutputStream(file + File.separator + "1.jpeg");// 6.使用網絡字節輸入流的方法 read 讀取客戶端發送過來的文件數據byte[] bytes = new byte[1024];int i = 0;while ((i = is.read(bytes)) != -1) {// 7.使用 FileOutputStream 對象的方法 write 將讀取到文件數據寫入到服務器本地文件中fos.write(bytes, 0, i);}// 8.使用 Socket 對象的方法 getOutputStream 獲取網絡字節輸出流對象OutputStream ops = socket.getOutputStream();// 9.使用網絡字節輸出流對象的方法 write 給客戶端發送一段文字:文件上傳成功!ops.write("文件上傳成功!".getBytes());// 10.釋放資源(FileOutputStream、Socket、ServerSocket)fos.close();socket.close();server.close();}}服務端的升級版本一:
package priv.lwx.javaex.fileupload;import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.Random;/*** @ClassName TCPServer* @Description 服務端讀取客戶端發送過來的文件數據,并寫入到指定的服務器本地的文件中* 在 TCPServer 的基礎上優化兩個地方* 1.自定義文件名,每次上傳文件的文件名都不同* 2.讓服務端一直處于監聽狀態,這樣就可以一直上傳圖片** @Author liaowenxiong* @Version 1.0* @date 2021/9/5 下午7:38*/ public class TCPServer02 {public static void main(String[] args) throws IOException {// 1.創建一個服務端對象(即 ServerSocket),并且向系統要指定的端口號ServerSocket server = new ServerSocket(8888);// 2.使用服務端對象的方法 accept 獲取請求的客戶端對象(即請求連接的 Socket 對象)// 通過死循環,可以讓服務端一直處于監聽狀態,只要有客戶端請求連接,服務端就可以響應連接請求while (true) {Socket socket = server.accept();// 3.使用 Socket 對象的方法 getInputStream 獲取網絡字節輸入流InputStream is = socket.getInputStream();// 4.判斷服務端的目標目錄路徑是否存在,若不存在要創建此目錄File file = new File("/Users/liaowenxiong/desktop/test/upload");if (!file.exists()) {file.mkdirs();}// 自定義文件名的規則String fileName = System.currentTimeMillis() + (new Random().nextInt(9) + 1) + ".jpeg";// 5.創建一個本地字節輸出流對象(即 FileOutputStream),構造方法中要綁定寫入數據的目標文件路徑FileOutputStream fos = new FileOutputStream(file + File.separator + fileName);// 6.使用網絡字節輸入流的方法 read 讀取客戶端發送過來的文件數據byte[] bytes = new byte[1024];int i = 0;while ((i = is.read(bytes)) != -1) {// 7.使用 FileOutputStream 對象的方法 write 將讀取到文件數據寫入到服務器本地文件中fos.write(bytes, 0, i);}// 8.使用 Socket 對象的方法 getOutputStream 獲取網絡字節輸出流對象OutputStream ops = socket.getOutputStream();// 9.使用網絡字節輸出流對象的方法 write 給客戶端發送一段文字:文件上傳成功!ops.write("文件上傳成功!".getBytes());// 10.釋放資源(FileOutputStream、Socket、ServerSocket)fos.close();socket.close();// 服務端不停止,服務端資源不要釋放// server.close();}}}服務端的升級版本二:
package priv.lwx.javaex.fileupload;import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.Random;/*** @ClassName TCPServer* @Description 服務端讀取客戶端發送過來的文件數據,并寫入到指定的服務器本地的文件中* 在 TCPServer02 基礎上優化* 使用多線程技術,提高程序的效率,有一個客戶端上傳文件,就開啟一個線程完成文件的上傳* @Author liaowenxiong* @Version 1.0* @date 2021/9/5 下午7:38*/ public class TCPServer03 {public static void main(String[] args) throws IOException {// 1.創建一個服務端對象(即 ServerSocket),并且向系統要指定的端口號ServerSocket server = new ServerSocket(8888);// 2.使用服務端對象的方法 accept 獲取請求的客戶端對象(即請求連接的 Socket 對象)// 通過死循環,可以讓服務端一直處于監聽狀態,只要有客戶端請求連接,服務端就可以響應連接請求while (true) {Socket socket = server.accept();// 使用多線程技術,提高文件上傳的效率,有一個客戶端上傳文件,就開啟一個線程完成文件的上傳new Thread(new Runnable() {// run 方法里面完成文件數據的讀取和寫入@Overridepublic void run() {FileOutputStream fos = null;try {// 3.使用 Socket 對象的方法 getInputStream 獲取網絡字節輸入流InputStream is = socket.getInputStream();// 4.判斷服務端的目標目錄路徑是否存在,若不存在要創建此目錄File file = new File("/Users/liaowenxiong/desktop/test/upload");if (!file.exists()) {file.mkdirs();}// 自定義文件名的規則String fileName = System.currentTimeMillis() + (new Random().nextInt(9) + 1) + ".jpeg";// 5.創建一個本地字節輸出流對象(即 FileOutputStream),構造方法中要綁定寫入數據的目標文件路徑fos = new FileOutputStream(file + File.separator + fileName);// 6.使用網絡字節輸入流的方法 read 讀取客戶端發送過來的文件數據byte[] bytes = new byte[1024];int i = 0;while ((i = is.read(bytes)) != -1) {// 7.使用 FileOutputStream 對象的方法 write 將讀取到文件數據寫入到服務器本地文件中fos.write(bytes, 0, i);}// 8.使用 Socket 對象的方法 getOutputStream 獲取網絡字節輸出流對象OutputStream ops = socket.getOutputStream();// 9.使用網絡字節輸出流對象的方法 write 給客戶端發送一段文字:文件上傳成功!ops.write("文件上傳成功!".getBytes());// 10.釋放資源(FileOutputStream、Socket、ServerSocket)} catch (IOException e) {// System.out.println(e);e.printStackTrace();} finally {try {fos.close();socket.close();// 服務端不停止,服務端資源不要釋放// server.close();} catch (IOException e) {e.printStackTrace();}}}}).start();}}} 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的通过Socket实现文件上传/上传文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 路由linux系统(路由linux)
- 下一篇: Artifact到底是什么