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

71 篇文章 0 订阅
35 篇文章 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:文件小于2M
		JFileChooser 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();//采用缓存流需要刷缓存,不然有BUG
		
		BufferedInputStream bis = new BufferedInputStream(
									  new FileInputStream( imagFile ) );
		
		//再数据对拷
		byte[] buf = new byte[1024]; //一次读1KB
		int len = bis.read( buf );
		while ( len != -1) {
			bos.write( buf, 0, len );
			bos.flush(); //采用缓存流需要刷缓存,不然有BUG
			len = 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;
	}

	@Override
	public 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 );
			///注意///
			//这里需要注意这里读取内容的大小 要与上传时定义的文件头大小一样 1024B
			bis = 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];// 一次拷1KB
			int 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) {
			}
		}
	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值