先上代码,最上方注释是文件名称(运行时要用到)

FTServer.java

 /*
FTServer.java
*/ import java.util.*;
import java.io.*; public class FTServer { public static File share = null; public static void main(String[] args) throws Exception { int port = ; //加载配置文件
Properties p = new Properties();
p.load(FTServer.class.getClassLoader().getResourceAsStream("server.properties")); //获取服务器的存储路径
share = new File(p.getProperty("share")); if(!share.isDirectory()) {
System.out.println("share directory not exists or isn't a directory");
System.exit(-);
} //读取服务器与客户机交互的端口号
port = Integer.parseInt(p.getProperty("port")); FTProtocol protocol = new FTProtocol();
AdvancedSupport as = new AdvancedSupport(protocol);
NwServer nw = new NwServer(as,port); } }

FTClient.java

 /*
FTClient.java
*/ import java.net.*;
import java.io.*;
import java.util.*; public class FTClient { Socket s = null;
DataInputStream dis = null;
DataOutputStream dos = null; String[] args = null; public void start(String server, int port) throws Exception {
s = establish(server, port);//new一个socket
dis = new DataInputStream(s.getInputStream());
dos = new DataOutputStream(s.getOutputStream()); if (args[].equals("get")) {//获取文件
dos.writeInt();//执行command为3的操作,对应FTProtocol中的case 3
dos.flush();//清空缓冲区数据
int files = dis.readInt();//得到目录中文件数量
if (files == ) {//目录中文件为空
System.out.println("no files available on the FTServer");
s.close();//关闭套接字
System.exit(-);//退出程序
}
String[] filenames = new String[files];
for (int i = ; i < files; i++) {
filenames[i] = dis.readUTF();//读取FTProtocol中通过writeUTF(files[i])发来的文件名
System.out.println(i + + "\t\t" + filenames[i]);//输出序号和文件名
} System.out.print("please input your choice:"); BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String c = br.readLine();//读取输入的命令选项 if (c.equalsIgnoreCase("q")) {//若输入'Q'或'q'则退出程序
s.close();//关闭套接字
System.exit();//退出程序
} if (c.equalsIgnoreCase("a")) {//若输入'A'或'a'则下载全部文件
for (int i = ; i < filenames.length; i++) {
System.out.println("filenames[i] = " + filenames[i]);
download(filenames[i]);//循环下载每一个文件
}
s.close();
System.exit();
}
int choice = ;
try {
choice = Integer.parseInt(c);//将字符串转换成整形
} catch (NumberFormatException e) {
System.out.println("your input is wrong");
s.close();
System.exit(-);
} //输入文件对应序号则下载该文件
if (choice >= && choice <= filenames.length) {
download(filenames[choice - ]);
} else {
System.out.println("your input is wrong");
s.close();
System.exit(-);
}
s.close();
System.exit();
} else if (args[].equals("put")) {//上传文件
File f = new File("C:/_Client/" + args[]);//args[2]为文件名
if (f.isFile()) {
upload("C:/_Client/" + args[]);
} else if (f.isDirectory()) {//如果上传的是一个目录
String[] filenames = f.list();//将目录中所有文件存入filenames数组
if (filenames.length == ) {
s.close();
System.out.println("no files available in the directory");
System.exit(-);
}
for (int i = ; i < filenames.length; i++) {//将目录中的文件列表显示
System.out.println(i + + "\t\t" + filenames[i]);
}
System.out.print("please input your choice:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String c = br.readLine(); if (c.equalsIgnoreCase("q")) {//若输入'Q'或'q'则退出程序
s.close();//关闭套接字
System.exit();//退出程序
} if (c.equalsIgnoreCase("a")) {//若输入'A'或'a'则上传全部文件
for (int i = ; i < filenames.length; i++) {
String dir = f.getCanonicalPath();//获取文件路径
String tf = null;
if (dir.endsWith(File.separator)) {//如果以分隔符结尾,则直接加上文件名
tf = dir + filenames[i];
} else {//否则加上分隔符再加文件名
tf = dir + File.separator + filenames[i];
}
//此时tf为文件的绝对路径
if(new File(tf).isDirectory()) continue;
upload(tf);
}
s.close();
System.exit();
}
int choice = ;
try {
choice = Integer.parseInt(c);
} catch (NumberFormatException e) {
System.out.println("your input is wrong");
s.close();
System.exit(-);
}
//上传第choice个文件
if (choice >= && choice <= filenames.length) {
String dir = f.getCanonicalPath();
if (dir.endsWith(File.separator)) {
upload(dir + filenames[choice - ]);
} else {
upload(dir + File.separator + filenames[choice - ]);
} } else {
System.out.println("your input is wrong");
s.close();
System.exit(-);
} } else {
s.close();
System.out.println(args[] + " not exists");
System.exit(-);
} s.close();
System.exit(); } } public Socket establish(String server, int port) {
try {
Socket s = new Socket(server, port);
return s;
} catch (Exception e) {
e.printStackTrace();
return null;
}
} public void upload(String filename) throws Exception { File f = new File(filename); if (!f.exists() || !f.isFile()) {
System.out.println("it's wrong, maybe it is not a file or not exists");
System.exit(-);
} byte[] buffer = new byte[];
int rr = ; dos.writeInt();//执行FTProtocol中的上传命令
dos.writeUTF(f.getName());//将文件名传递给FTProtocol
dos.writeLong(f.length());//将文件长度传递给FTProtocol
dos.flush();//清空缓存 FileInputStream fis = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(fis); while ((rr = bis.read(buffer)) != -) {
dos.write(buffer, , rr);
dos.flush();
} bis.close();
fis.close(); } public void download(String filename) throws Exception {
dos.writeInt();//执行FTProtocol中的下载命令
dos.writeUTF(filename);//将要下载的文件名传递给FTProtocol
dos.flush(); //filename = dis.readUTF();
long len = dis.readLong();//获得文件长度 byte[] buffer = new byte[];
long r = ;
int rr = ; //将先下载后的文件输出到C盘的_Client文件夹
FileOutputStream fos = new FileOutputStream("C:/_Client/" + filename);
BufferedOutputStream bos = new BufferedOutputStream(fos); while (r < len) {
if (len - r >= buffer.length) {//若文件未传输的部分大于buffer的长度则每次传输buffer.length的字节
rr = dis.read(buffer, , buffer.length);
} else {//将剩余(小于buffer.length)的数据传输
rr = dis.read(buffer, , (int) (len - r));
}
r = r + rr;
bos.write(buffer, , rr);//将下次传输可接收的字节传递给FTProtocol,rr=-1则传输结束
} bos.close();
fos.close(); System.out.println("download Finished!"); } public static void main(String[] args) throws Exception {
if(args.length==) {
System.out.println("Usage:");
System.out.println("java FTClient host get");
System.out.println("java FTClient host put afile");
System.exit(); }
FTClient ftc = new FTClient();
ftc.args = args;
ftc.start(args[], );//args[0]为host
}
}

FTProtocol.java

 import java.net.Socket;
/*
FTProtocol.java
*/ import java.io.*;
import java.util.*; //与AdvancedSupport都implements IOStrategy,都重写了service()函数
public class FTProtocol implements IOStrategy { @Override
public void service(Socket socket) {
String client = socket.getInetAddress().getHostName() + "(" + socket.getInetAddress().getHostAddress() + ")"; try {
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
DataInputStream dis = new DataInputStream(is);
DataOutputStream dos = new DataOutputStream(os); String filename = null;
long len = ;
byte[] buffer = new byte[];
long r = ;
int rr = ; while (true) {
int command = dis.readInt(); // 读取FTClient中通过writeInt()传来的命令
switch (command) {
case : // file upload
filename = dis.readUTF();//接收文件名
len = dis.readLong();//接收文件长度 //将用户上传文件存到FTServer.share目录中
FileOutputStream fos = new FileOutputStream(new File(FTServer.share, filename));
BufferedOutputStream bos = new BufferedOutputStream(fos);
r = ;
rr = ; while (r < len) {
if (len - r >= buffer.length) {
rr = dis.read(buffer, , buffer.length);
} else {
rr = dis.read(buffer, , (int) (len - r));
} r = r + rr;
bos.write(buffer, , rr);
} bos.close();
fos.close();
break;
case : // file download
filename = dis.readUTF();
//dos.writeUTF(filename);
File t = new File(FTServer.share, filename);
//System.out.println("FTServer.share = " + FTServer.share);
dos.writeLong(t.length());//将文件长度传递给FTClient
dos.flush();//清空缓存
FileInputStream fis = new FileInputStream(t);
BufferedInputStream bis = new BufferedInputStream(fis); while ((rr = bis.read(buffer)) != -) {//接收到下次可发送的字节数,-1结束
dos.write(buffer, , rr);
dos.flush();
} bis.close();
fis.close();
break; case : // list files
String[] files = FTServer.share.list();//将share目录下所有文件名存入files数组
List<String> list = new LinkedList<String>();
for(int i=;i<files.length;i++) {
if(new File(FTServer.share, files[i]).isDirectory())
continue;//如果是一个目录则不显示
list.add(files[i]);
} files = list.toArray(new String[]);//将List<String>转换成String[] dos.writeInt(files.length);//将文件数量传给FTClient
dos.flush();//清空缓存
for (int i = ; i < files.length; i++) {
dos.writeUTF(files[i]);//将每一个文件名传给FTClient
}
dos.flush();//清空缓存
break;
}
}
} catch (Exception e) {
if (e instanceof EOFException) {
System.out.println(client + " disconnected");
} else {
e.printStackTrace();
} }
}
}

AdvancedSupport.java

 /*
AdvancedSupport.java
*/ import java.net.*;
import java.io.*;
import java.util.*; //与FTProtocol都implements IOStrategy,都重写了service()函数
public class AdvancedSupport implements IOStrategy {
private ArrayList threads = new ArrayList();//开线程数组
private final int INIT_THREADS = ;//初始线程数
private final int MAX_THREADS = ;//最大线程数
private IOStrategy ios = null;//初始化 //构造函数
public AdvancedSupport(IOStrategy ios) {
this.ios = ios; for (int i = ; i < INIT_THREADS; i++) {
IOThread t = new IOThread(ios);
t.start();
threads.add(t);
}
try {
Thread.sleep();
} catch (Exception e) {
}
} public void service(Socket socket) {
IOThread t = null;
boolean found = false; //顺序找到线程中第一个等待的IOThread,将found置为true并退出循环
for (int i = ; i < threads.size(); i++) {
t = (IOThread) threads.get(i);
if (t.isIdle()) {
found = true;
break;
}
} //若Thread中不存在等待的线程,则新建一个线程并启动
if (!found) {
t = new IOThread(ios);
t.start();
try {
Thread.sleep();
} catch (Exception e) {
}
//将新建线程添加到threads数组中
threads.add(t);
} //将socket赋值为传来的socket参数
t.setSocket(socket);
}
} class IOThread extends Thread {
private Socket socket = null;
private IOStrategy ios = null; public IOThread(IOStrategy ios) {
this.ios = ios;
} public boolean isIdle() {
return socket == null;
} public synchronized void setSocket(Socket socket) {
this.socket = socket;
notify();//唤醒
} public synchronized void run() {
while (true) {
try {
wait();//等待到setSocket执行notify()后,调用service()
ios.service(socket);
socket = null;//service()结束后,套接字置为空
} catch (Exception e) {
e.printStackTrace();
}
}
}
};

IOStrategy.java

 /*
IOStrategy.java
*/ import java.net.*; /*
提供协议策略定义
*/ public interface IOStrategy
{
public void service(Socket socket);
}

NwServer.java

 /*
NwServer.java
*/ import java.net.*; /*
实现网络通信,可以服务于任何应用,没有提供协议,
也就是说NwServer可以适用于任何协议。
*/ public class NwServer
{
private int port = ; //没有处理端口 public NwServer(IOStrategy io, int port) throws Exception {
//它只负责接受客户端的连接请求,建立网络建立(socket连接)
//然后将连接提交给协议处理程序。 this.port = port; ServerSocket server = new ServerSocket(port);
System.out.println("FTServer is ready"); while(true)
{
//接受客户端的连接请求
Socket socket = server.accept(); //获取客户端地址
InetAddress ia = socket.getInetAddress();
System.out.println(ia.getHostName() + "(" + ia.getHostAddress() + ") connected."); //将连接提交给协议处理程序
io.service(socket);
}
}
}

server.properties配置文件:

 share=C:\\_Server
port=

效果展示:

首先看一下客户端和服务器端的存储空间内的文件:

服务器:

客户端:

1.编译

2.再开一个窗口,分别运行FTServer和FTClient

(1)get命令,得到服务器中的全部文件列表显示(文件夹不显示)

(2)·choice输入文件序号则下载对应文件

  ·choice输入a或A则下载全部文件

  ·choice输入q或Q则退出

(3)put命令,客户端向服务器上传文件(若是一个文件夹则显示文件夹中内容)

·直接上传文件名

·上传文件夹

choice选项基本和下载时一样:

输入a或A则上传全部文件,输入q或Q则退出,输入文件序号则上传对应文件,不再截图。

[Java] 文件上传下载项目(详细注释)的更多相关文章

  1. 2013第38周日Java文件上传下载收集思考

    2013第38周日Java文件上传&下载收集思考 感觉文件上传及下载操作很常用,之前简单搜集过一些东西,没有及时学习总结,现在基本没啥印象了,今天就再次学习下,记录下自己目前知识背景下对该类问 ...

  2. ssm文件上传下载比较详细的案例

    背景:ssm框架 接下来,我会介绍单文件上传,下载,多文件的上传,下载,使用ajax进行文件的上传下载,和普通的表单提交的文件上传下载. 只要做项目,总是少不了文件的操作,好了废话不多说,直接上代码! ...

  3. Java文件上传下载原理

    文件上传下载原理 在TCP/IP中,最早出现的文件上传机制是FTP.它是将文件由客户端发送到服务器的标准机制. 但是在jsp编程中不能使用FTP方法来上传文件,这是由jsp运行机制所决定的 文件上传原 ...

  4. java文件上传下载组件

    需求: 支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验: 内网百兆网络上传速度为12MB/S 服务器内存占用低 支持文件夹上传,文件夹中的文件数量达到1万个以上,且包 ...

  5. java 文件上传下载

    翻新十年前的老项目,文件上传改为调用接口方式,记录一下子~~~ java后台代码: //取配置文件中的上传目录 @Value("${uploadPath}") String pat ...

  6. java文件上传下载

    文件上传首先要引入两个核心包 commons-fileupload-1.2.1.jar commons-io-1.4.jar 下面是对文件上传和下载的一些代码做的一个简单封装,可以方便以后直接使用[使 ...

  7. java 文件上传 下载 总结

    首先引入2个jar ![](http://images2017.cnblogs.com/blog/1128666/201711/1128666-20171101145630498-2084371020 ...

  8. java文件上传下载解决方案

    javaweb上传文件 上传文件的jsp中的部分 上传文件同样可以使用form表单向后端发请求,也可以使用 ajax向后端发请求 1.通过form表单向后端发送请求 <form id=" ...

  9. java文件上传下载 使用SmartUpload组件实现

    使用SmartUpload组件实现(下载jsmartcom_zh_CN.jar) 2017-11-07 1.在WebRoot创建以下文件夹,css存放样式文件(css文件直接拷贝进去),images存 ...

随机推荐

  1. 修改pytorch官方实例适用于自己的二分类迁移学习项目

    本demo从pytorch官方的迁移学习示例修改而来,增加了以下功能: 根据AUC来迭代最优参数: 五折交叉验证: 输出验证集错误分类图片: 输出分类报告并保存AUC结果图片. import os i ...

  2. thinkphp 下多图ajax上传图片

    碰到一个项目,有一个比较繁琐的功能6个ajax上传,基本上每个上传逻辑多不一样,记录一下 thinkphp的view页面: id方便找到这个元素 name一定要加 [ ] <div class= ...

  3. vue.js 组件-全局组件和局部组件

    这两天学习了Vue.js 感觉组件这个地方知识点挺多的,而且很重要,所以,今天添加一点小笔记. 首先Vue组件的使用有3个步骤,创建组件构造器,注册组件,使用组件3个方面. 代码演示如下: <! ...

  4. Docker(二):Hello World

    Docker 安装 这里以CentOS7 为例,其他安装教程可以自行通过其他路径了解. Docker 运行在CentOS7 上要求,系统为64位.系统内核版本为3.10以上. Docker 运行在 C ...

  5. php使用file_get_contents 或者curl 发送get/post 请求 的方法总结

    file_get_contents模拟GET/POST请求 模拟GET请求: <?php $data = array( 'name'=>'zhezhao', 'age'=>'23' ...

  6. MetInfo最新网站漏洞如何修复以及网站安全防护

    metinfo漏洞于2018年10月20号被爆出存在sql注入漏洞,可以直接拿到网站管理员的权限,网站漏洞影响范围较广,包括目前最新的metinfo版本都会受到该漏洞的攻击,该metinfo漏洞产生的 ...

  7. P3305 [SDOI2013]费用流

    题目描述 Alice和Bob在图论课程上学习了最大流和最小费用最大流的相关知识. 最大流问题:给定一张有向图表示运输网络,一个源点S和一个汇点T,每条边都有最大流量. 一个合法的网络流方案必须满足: ...

  8. Java线程和多线程(九)——死锁

    Java中的死锁指的就是一种多于两个线程永远阻塞的特殊状况.Java中的死锁状态至少需要多于两个线程以及资源的时候才会产生.这里,我写了一个产生死锁的程序,并且讲下如何分析死锁. 首先来看一下产生死锁 ...

  9. 3155: Preprefix sum

    3155: Preprefix sum https://www.lydsy.com/JudgeOnline/problem.php?id=3155 分析: 区间修改,区间查询,线段树就好了. 然后,这 ...

  10. Android TV 开发(3)

    本文来自网易云社区 作者:孙有军   <LinearLayout         android:id="@+id/input_num_line_3"         and ...