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