当前位置: 代码迷 >> 综合 >> Java---net(网络编程)---TCP---文件传输
  详细解决方案

Java---net(网络编程)---TCP---文件传输

热度:17   发布时间:2023-10-21 17:31:45.0

上传文本文件

需求:读取一个本地文本文件,将数据发送到服务端,服务器端对数据进行存储。 存储完毕后,给客户端一个提示。

代码:

客户端:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;/*** 2018年5月10日 上午10:52:53* @author <a href="mailto:447441478@qq.com">宋进宇</a>*	客户端上传 “文本文件”*/
public class Client {//这里为了代码 简洁 直接抛异常public static void main(String[] args) throws IOException {//尝试与服务器 “握手”--建立连接Socket s = new Socket( InetAddress.getByName( "127.0.0.1" ), 8888);//能到这里说明握手成功,进行文本文件上传//文件源:本地磁盘//目的:服务器//存文本,加缓存BufferedReader br = new BufferedReader(new FileReader( "a.txt" ) );//在网络传输中最好采用 PrintWriter 进行 输出,并且可以设置自动刷缓存,//注意自动刷缓存只对 println、printf或format 三个方法有用PrintWriter pw = new PrintWriter( s.getOutputStream(),true);//进行数据对拷String str = br.readLine();while ( str != null ) {pw.println( str );//如果没有设置 自动刷缓存 需要  pw.flush();str = br.readLine();}s.shutdownOutput();br.close();//不是 Socket 中的输入或输出流可以关//pw.close();只要还有传输数据就不能 关掉 Socket中的 输入流或输出流//接收 服务器 的提示:是否上传成功InputStream in = s.getInputStream();BufferedReader br2 = new BufferedReader( new InputStreamReader( in, "UTF-8" ) );String mes = br2.readLine();while ( mes != null ) {System.out.println( mes );mes = br2.readLine();}in.close();br2.close();s.close();}
}

服务器端:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;/*** 2018年5月10日 上午11:10:21* @author <a href="mailto:447441478@qq.com">宋进宇</a>*	接收客户端上传的 “文本文件”*/
public class Server {//这里为了代码 简洁 直接抛异常public static void main(String[] args) throws IOException {//打开服务器 ServerSocket server = new ServerSocket( 8888 );//等待 客户端来 “握手” --建立连接Socket s = server.accept();//能到这里说明 客户端与服务器 建立了连接//进行接收上传的文件//源:客户端 //类型:纯文本文件 //目的:本地磁盘InputStream in = s.getInputStream();BufferedReader br = new BufferedReader( new InputStreamReader( in, "UTF-8" ) );PrintWriter pw = new PrintWriter( "server.txt" );//进行数据对拷String str = br.readLine();while ( str != null ) {pw.println( str );pw.flush();//这里就演示没有 设置自动刷缓存 ,需手动刷缓存str = br.readLine();}//br.close(); 不能关!!!pw.close(); //不是 Socket 中的输入或输出流可以关//能到这里说明 文件上传 成功 给用户发送提示PrintWriter pw2 = new PrintWriter( s.getOutputStream(), true );pw2.println( "文件上传 成功!!" );s.shutdownOutput();s.close();server.close();}
}

上传图片文件

    客户端需求:
把一个图片文件发送到服务端并读取回馈信息。要求判断文件是否存在及 格式是否为jpg或gif并要求文件小于2M。
    服务端需求:
接收客户端发送过来的图片数据。进行存储后,回馈一个 上传成功字样。 支持多用户的并发访问

代码:

客户端:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;import javax.swing.JFileChooser;
import javax.swing.JOptionPane;/*** 2018年5月10日 下午3:03:07* @author <a href="mailto:447441478@qq.com">宋进宇</a>*	把一个图片文件发送到服务端并读取回馈信息。*	要求判断文件是否存在及格式是否为jpg或gif并要求文件小于2M*/
public class Client {//为了 代码简洁 直接抛异常public static void main(String[] args) throws IOException {//先判断是否符合上传的要求//要求1:文件是否存在//要求2:格式是否为jpg或gif//要求3:文件小于2MJFileChooser jfc = new JFileChooser();int sel = jfc.showOpenDialog( null );File imagFile = null;if ( sel == JFileChooser.APPROVE_OPTION ) {imagFile = jfc.getSelectedFile();}if ( imagFile == null ) {return ;}//如果文件不存在,就结束if ( !imagFile.exists() || imagFile.isDirectory() ) {JOptionPane.showMessageDialog(null, "文件不存在" );return;}//能到这里说明文件存在,接下来进行格式校验//如果不是 jpg或gif 就结束if ( !( imagFile.getName().endsWith( ".jpg" ) || imagFile.getName().endsWith( ".gif" ) ) ) {JOptionPane.showMessageDialog(null, "文件格式不符合,只能是jpg或者gif格式" );return;}//能到这里说明上面的要求符合,进行最后的校验if ( imagFile.length() >= 2*1024*1024 ) {JOptionPane.showMessageDialog(null, "文件太大" );return;}//与服务器 建立连接Socket s = new Socket( "113.242.149.32", 8888 );//能到这里 说明 已经建立连接//程序能到这里说明可以进行上传了//因为文件是 图片 类型 为了不失真 采用字节流//考虑到速度问题 可以加个缓存BufferedOutputStream bos = new BufferedOutputStream( s.getOutputStream() );//先发送文件名//这里需要定义一个协议--文件名协议 ,就是 文件名长度不能超过 1024-1 个字节byte[] fileName = new byte[1024];//采用 UTF-8 码表进行编码byte[] bytes = ( imagFile.getName() + "\n" ).getBytes( "UTF-8" );if ( bytes.length > 1024 ) {JOptionPane.showMessageDialog(null, "文件名长度太长!必须小于1023个字节");}//采用系统的数组拷贝函数System.arraycopy( bytes, 0, fileName, 0, bytes.length );bos.write( fileName, 0, 1024 );bos.flush();//采用缓存流需要刷缓存,不然有BUGBufferedInputStream bis = new BufferedInputStream(new FileInputStream( imagFile ) );//再数据对拷byte[] buf = new byte[1024]; //一次读1KBint len = bis.read( buf );while ( len != -1) {bos.write( buf, 0, len );bos.flush(); //采用缓存流需要刷缓存,不然有BUGlen = bis.read( buf );}//关闭  输入流bis.close();//并且做一个标识--文件接收标识s.shutdownOutput();//接收 服务器端 反馈BufferedReader br = new BufferedReader(	new InputStreamReader( s.getInputStream(), "UTF-8" ) );//读取 服务器反馈的内容String mes = br.readLine();JOptionPane.showMessageDialog( null, mes );s.close();}
}

服务器端:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;/*** 2018年5月10日 下午3:27:09* * @author <a href="mailto:447441478@qq.com">宋进宇</a> 接收客户端发送过来的图片数据。 进行存储后,回馈一个*         上传成功字样。 支持多用户的并发访问。*/
public class Server {public static void main(String[] args) {ServerSocket server = null;try {// 服务器对外提供 一个 进行连接的端口server = new ServerSocket( 8888 );// 等待客户端 进行建立连接while (true) {Socket s = server.accept();// 能到这里说明用户连接成功// 为了支持多用户的并发访问,采用多线程进行处理new Thread(new Upload(s)).start();}} catch (IOException e) {e.printStackTrace();} }
}class Upload implements Runnable {private Socket s = null;public Upload(Socket s) {this.s = s;}@Overridepublic void run() {// 如果s为空直接结束if (s == null) {return;}// 先获取地址InetAddress clientIp = s.getInetAddress();PrintStream ps = null;BufferedInputStream bis = null;BufferedOutputStream bos = null;// 再获取文件名称try {ps = new PrintStream( s.getOutputStream(), true );///注意/////这里需要注意这里读取内容的大小 要与上传时定义的文件头大小一样 1024Bbis = new BufferedInputStream( s.getInputStream() );byte[] b = new byte[1024];bis.read( b );int i = 0;for ( ; i < b.length; i++ ) {if ( b[i] == 10 ) {break;}}//获取文件名(采用 UTF-8 码表进行解码)String imagFilename = new String( b, 0, i, "UTF-8" );//System.out.println( imagFilename );/////每个ip都对应一个文件夹File imagDir = new File( "netFiles\\imag\\" + clientIp.getHostAddress() );if ( !imagDir.exists() ) {imagDir.mkdirs();}//给文件名加个前缀int count = 1;File imagFile = new File( imagDir, (count++) +"_"+ imagFilename );//进行文件重名处理while (imagFile.exists()) {imagFile = new File( imagDir, (count++) +"_"+ imagFilename );}imagFile.createNewFile();// 进行数据对拷bos = new BufferedOutputStream( new FileOutputStream( imagFile ) );byte[] buf = new byte[1024];// 一次拷1KBint len = bis.read( buf );while (len != -1) {bos.write( buf, 0, len );bos.flush();len = bis.read( buf );}bos.close();// 能到这里说明文件上传成功,给客户端 反馈ps.println("文件上传成功!");} catch (IOException e) {System.out.println(e.getMessage());if (ps != null) {ps.println("文件上传失败!!!");try {s.shutdownOutput();} catch (IOException e1) {}}} finally {try {if (s != null) {s.close();}} catch (IOException e) {}}}}