zoukankan      html  css  js  c++  java
  • [Java] 文件上传下载项目(详细注释)

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

    FTServer.java

     1 /*
     2     FTServer.java
     3 */
     4 
     5 import java.util.*;
     6 import java.io.*;
     7 
     8 public class FTServer {
     9     
    10     public static File share = null;
    11     
    12     public static void main(String[] args) throws Exception  {
    13         
    14         int port = 4321;
    15         
    16         //加载配置文件
    17         Properties p = new Properties();
    18         p.load(FTServer.class.getClassLoader().getResourceAsStream("server.properties"));
    19         
    20         //获取服务器的存储路径
    21         share = new File(p.getProperty("share"));
    22         
    23         if(!share.isDirectory()) {
    24             System.out.println("share directory not exists or isn't a directory");
    25             System.exit(-4);
    26         }
    27         
    28         //读取服务器与客户机交互的端口号
    29         port = Integer.parseInt(p.getProperty("port"));
    30         
    31         FTProtocol protocol = new FTProtocol();
    32         AdvancedSupport as = new AdvancedSupport(protocol);
    33         NwServer nw = new NwServer(as,port);
    34             
    35     }
    36 
    37 }
    View Code

    FTClient.java

      1 /*
      2     FTClient.java
      3 */
      4 
      5 import java.net.*;
      6 import java.io.*;
      7 import java.util.*;
      8 
      9 public class FTClient {
     10 
     11     Socket s = null;
     12     DataInputStream dis = null;
     13     DataOutputStream dos = null;
     14 
     15     String[] args = null;
     16 
     17     public void start(String server, int port) throws Exception {
     18         s = establish(server, port);//new一个socket
     19         dis = new DataInputStream(s.getInputStream());
     20         dos = new DataOutputStream(s.getOutputStream());
     21 
     22         if (args[1].equals("get")) {//获取文件
     23             dos.writeInt(3);//执行command为3的操作,对应FTProtocol中的case 3
     24             dos.flush();//清空缓冲区数据
     25             int files = dis.readInt();//得到目录中文件数量
     26             if (files == 0) {//目录中文件为空
     27                 System.out.println("no files available on the FTServer");
     28                 s.close();//关闭套接字
     29                 System.exit(-1);//退出程序
     30             }
     31             String[] filenames = new String[files];
     32             for (int i = 0; i < files; i++) {
     33                 filenames[i] = dis.readUTF();//读取FTProtocol中通过writeUTF(files[i])发来的文件名
     34                 System.out.println(i + 1 + "		" + filenames[i]);//输出序号和文件名
     35             }
     36 
     37             System.out.print("please input your choice:");
     38 
     39             BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
     40             String c = br.readLine();//读取输入的命令选项
     41 
     42             if (c.equalsIgnoreCase("q")) {//若输入'Q'或'q'则退出程序
     43                 s.close();//关闭套接字
     44                 System.exit(0);//退出程序
     45             }
     46 
     47             if (c.equalsIgnoreCase("a")) {//若输入'A'或'a'则下载全部文件
     48                 for (int i = 0; i < filenames.length; i++) {
     49                     System.out.println("filenames[i] = " + filenames[i]);
     50                     download(filenames[i]);//循环下载每一个文件
     51                 }
     52                 s.close();
     53                 System.exit(0);
     54             }
     55             int choice = 0;
     56             try {
     57                 choice = Integer.parseInt(c);//将字符串转换成整形
     58             } catch (NumberFormatException e) {
     59                 System.out.println("your input is wrong");
     60                 s.close();
     61                 System.exit(-2);
     62             }
     63             
     64             //输入文件对应序号则下载该文件
     65             if (choice >= 1 && choice <= filenames.length) {
     66                 download(filenames[choice - 1]);
     67             } else {
     68                 System.out.println("your input is wrong");
     69                 s.close();
     70                 System.exit(-5);
     71             }
     72             s.close();
     73             System.exit(0);
     74         } else if (args[1].equals("put")) {//上传文件
     75             File f = new File("C:/_Client/" + args[2]);//args[2]为文件名
     76             if (f.isFile()) {
     77                 upload("C:/_Client/" + args[2]);
     78             } else if (f.isDirectory()) {//如果上传的是一个目录
     79                 String[] filenames = f.list();//将目录中所有文件存入filenames数组
     80                 if (filenames.length == 0) {
     81                     s.close();
     82                     System.out.println("no files available in the directory");
     83                     System.exit(-8);
     84                 }
     85                 for (int i = 0; i < filenames.length; i++) {//将目录中的文件列表显示
     86                     System.out.println(i + 1 + "		" + filenames[i]);
     87                 }
     88                 System.out.print("please input your choice:");
     89                 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
     90                 String c = br.readLine();
     91 
     92                 if (c.equalsIgnoreCase("q")) {//若输入'Q'或'q'则退出程序
     93                     s.close();//关闭套接字
     94                     System.exit(0);//退出程序
     95                 }
     96 
     97                 if (c.equalsIgnoreCase("a")) {//若输入'A'或'a'则上传全部文件
     98                     for (int i = 0; i < filenames.length; i++) {
     99                         String dir = f.getCanonicalPath();//获取文件路径
    100                         String tf = null;
    101                         if (dir.endsWith(File.separator)) {//如果以分隔符结尾,则直接加上文件名
    102                             tf = dir + filenames[i];
    103                         } else {//否则加上分隔符再加文件名
    104                             tf = dir + File.separator + filenames[i];
    105                         }
    106                         //此时tf为文件的绝对路径
    107                         if(new File(tf).isDirectory()) continue;
    108                         upload(tf);
    109                     }
    110                     s.close();
    111                     System.exit(0);
    112                 }
    113                 int choice = 0;
    114                 try {
    115                     choice = Integer.parseInt(c);
    116                 } catch (NumberFormatException e) {
    117                     System.out.println("your input is wrong");
    118                     s.close();
    119                     System.exit(-2);
    120                 }
    121                 //上传第choice个文件
    122                 if (choice >= 1 && choice <= filenames.length) {
    123                     String dir = f.getCanonicalPath();
    124                     if (dir.endsWith(File.separator)) {
    125                         upload(dir + filenames[choice - 1]);
    126                     } else {
    127                         upload(dir + File.separator + filenames[choice - 1]);
    128                     }
    129 
    130                 } else {
    131                     System.out.println("your input is wrong");
    132                     s.close();
    133                     System.exit(-5);
    134                 }
    135 
    136             } else {
    137                 s.close();
    138                 System.out.println(args[2] + " not exists");
    139                 System.exit(-7);
    140             }
    141 
    142             s.close();
    143             System.exit(0);
    144 
    145         }
    146 
    147     }
    148 
    149     public Socket establish(String server, int port) {
    150         try {
    151             Socket s = new Socket(server, port);
    152             return s;
    153         } catch (Exception e) {
    154             e.printStackTrace();
    155             return null;
    156         }
    157     }
    158 
    159     public void upload(String filename) throws Exception {
    160         
    161         File f = new File(filename);
    162 
    163         if (!f.exists() || !f.isFile()) {
    164             System.out.println("it's wrong, maybe it is not a file or not exists");
    165             System.exit(-6);
    166         }
    167 
    168         byte[] buffer = new byte[4096];
    169         int rr = 0;
    170 
    171         dos.writeInt(1);//执行FTProtocol中的上传命令
    172         dos.writeUTF(f.getName());//将文件名传递给FTProtocol
    173         dos.writeLong(f.length());//将文件长度传递给FTProtocol
    174         dos.flush();//清空缓存
    175 
    176         FileInputStream fis = new FileInputStream(f);
    177         BufferedInputStream bis = new BufferedInputStream(fis);
    178 
    179         while ((rr = bis.read(buffer)) != -1) {
    180             dos.write(buffer, 0, rr);
    181             dos.flush();
    182         }
    183 
    184         bis.close();
    185         fis.close();
    186 
    187     }
    188 
    189     public void download(String filename) throws Exception {
    190         dos.writeInt(2);//执行FTProtocol中的下载命令
    191         dos.writeUTF(filename);//将要下载的文件名传递给FTProtocol
    192         dos.flush();
    193 
    194         //filename = dis.readUTF();
    195         long len = dis.readLong();//获得文件长度
    196 
    197         byte[] buffer = new byte[4096];
    198         long r = 0;
    199         int rr = 0;
    200         
    201         //将先下载后的文件输出到C盘的_Client文件夹
    202         FileOutputStream fos = new FileOutputStream("C:/_Client/" + filename);
    203         BufferedOutputStream bos = new BufferedOutputStream(fos);
    204 
    205         while (r < len) {
    206             if (len - r >= buffer.length) {//若文件未传输的部分大于buffer的长度则每次传输buffer.length的字节
    207                 rr = dis.read(buffer, 0, buffer.length);
    208             } else {//将剩余(小于buffer.length)的数据传输
    209                 rr = dis.read(buffer, 0, (int) (len - r));
    210             }
    211             r = r + rr;
    212             bos.write(buffer, 0, rr);//将下次传输可接收的字节传递给FTProtocol,rr=-1则传输结束
    213         }
    214 
    215         bos.close();
    216         fos.close();
    217         
    218         System.out.println("download Finished!");
    219 
    220     }
    221 
    222     public static void main(String[] args) throws Exception {
    223         if(args.length==0) {
    224             System.out.println("Usage:");
    225             System.out.println("java FTClient host get");
    226             System.out.println("java FTClient host put afile");
    227             System.exit(0);
    228             
    229         }
    230         FTClient ftc = new FTClient();
    231         ftc.args = args;
    232         ftc.start(args[0], 4321);//args[0]为host
    233     }
    234 }
    View Code

    FTProtocol.java

      1 import java.net.Socket;
      2 /*
      3     FTProtocol.java
      4 */
      5 
      6 import java.io.*;
      7 import java.util.*;
      8 
      9 //与AdvancedSupport都implements IOStrategy,都重写了service()函数
     10 public class FTProtocol implements IOStrategy {
     11 
     12     @Override
     13     public void service(Socket socket) {
     14         String client = socket.getInetAddress().getHostName() + "(" + socket.getInetAddress().getHostAddress() + ")";
     15 
     16         try {
     17             InputStream is = socket.getInputStream();
     18             OutputStream os = socket.getOutputStream();
     19             DataInputStream dis = new DataInputStream(is);
     20             DataOutputStream dos = new DataOutputStream(os);
     21 
     22             String filename = null;
     23             long len = 0;
     24             byte[] buffer = new byte[4096];
     25             long r = 0;
     26             int rr = 0;
     27 
     28             while (true) {
     29                 int command = dis.readInt(); // 读取FTClient中通过writeInt()传来的命令
     30                 switch (command) {
     31                 case 1: // file upload
     32                     filename = dis.readUTF();//接收文件名
     33                     len = dis.readLong();//接收文件长度
     34                     
     35                     //将用户上传文件存到FTServer.share目录中
     36                     FileOutputStream fos = new FileOutputStream(new File(FTServer.share, filename));
     37                     BufferedOutputStream bos = new BufferedOutputStream(fos);
     38                     r = 0;
     39                     rr = 0;
     40 
     41                     while (r < len) {
     42                         if (len - r >= buffer.length) {
     43                             rr = dis.read(buffer, 0, buffer.length);
     44                         } else {
     45                             rr = dis.read(buffer, 0, (int) (len - r));
     46                         }
     47 
     48                         r = r + rr;
     49                         bos.write(buffer, 0, rr);
     50                     }
     51 
     52                     bos.close();
     53                     fos.close();
     54                     break;
     55                 case 2: // file download
     56                     filename = dis.readUTF();
     57                     //dos.writeUTF(filename);
     58                     File t = new File(FTServer.share, filename);
     59                     //System.out.println("FTServer.share = " + FTServer.share);
     60                     dos.writeLong(t.length());//将文件长度传递给FTClient
     61                     dos.flush();//清空缓存
     62                     FileInputStream fis = new FileInputStream(t);
     63                     BufferedInputStream bis = new BufferedInputStream(fis);
     64 
     65                     while ((rr = bis.read(buffer)) != -1) {//接收到下次可发送的字节数,-1结束
     66                         dos.write(buffer, 0, rr);
     67                         dos.flush();
     68                     }
     69 
     70                     bis.close();
     71                     fis.close();
     72                     break;
     73 
     74                 case 3: // list files
     75                     String[] files = FTServer.share.list();//将share目录下所有文件名存入files数组
     76                     List<String> list = new LinkedList<String>();
     77                     for(int i=0;i<files.length;i++) {
     78                         if(new File(FTServer.share, files[i]).isDirectory()) 
     79                             continue;//如果是一个目录则不显示
     80                         list.add(files[i]);
     81                     }
     82                     
     83                     files = list.toArray(new String[0]);//将List<String>转换成String[]
     84                     
     85                     dos.writeInt(files.length);//将文件数量传给FTClient
     86                     dos.flush();//清空缓存
     87                     for (int i = 0; i < files.length; i++) {
     88                         dos.writeUTF(files[i]);//将每一个文件名传给FTClient
     89                     }
     90                     dos.flush();//清空缓存
     91                     break;
     92                 }
     93             }
     94         } catch (Exception e) {
     95             if (e instanceof EOFException) {
     96                 System.out.println(client + " disconnected");
     97             } else {
     98                 e.printStackTrace();
     99             }
    100 
    101         }
    102     }
    103 }
    View Code

    AdvancedSupport.java

     1 /*
     2     AdvancedSupport.java
     3 */
     4 
     5 import java.net.*;
     6 import java.io.*;
     7 import java.util.*;
     8 
     9 //与FTProtocol都implements IOStrategy,都重写了service()函数
    10 public class AdvancedSupport implements IOStrategy {
    11     private ArrayList threads = new ArrayList();//开线程数组
    12     private final int INIT_THREADS = 10;//初始线程数
    13     private final int MAX_THREADS = 100;//最大线程数
    14     private IOStrategy ios = null;//初始化
    15 
    16     //构造函数
    17     public AdvancedSupport(IOStrategy ios) {
    18         this.ios = ios;
    19 
    20         for (int i = 0; i < INIT_THREADS; i++) {
    21             IOThread t = new IOThread(ios);
    22             t.start();
    23             threads.add(t);
    24         }
    25         try {
    26             Thread.sleep(300);
    27         } catch (Exception e) {
    28         }
    29     }
    30     
    31     public void service(Socket socket) {
    32         IOThread t = null;
    33         boolean found = false;
    34         
    35         //顺序找到线程中第一个等待的IOThread,将found置为true并退出循环
    36         for (int i = 0; i < threads.size(); i++) {
    37             t = (IOThread) threads.get(i);
    38             if (t.isIdle()) {
    39                 found = true;
    40                 break;
    41             }
    42         }
    43         
    44         //若Thread中不存在等待的线程,则新建一个线程并启动
    45         if (!found) {
    46             t = new IOThread(ios);
    47             t.start();
    48             try {
    49                 Thread.sleep(30);
    50             } catch (Exception e) {
    51             }
    52             //将新建线程添加到threads数组中
    53             threads.add(t);
    54         }
    55         
    56         //将socket赋值为传来的socket参数
    57         t.setSocket(socket);
    58     }
    59 }
    60 
    61 class IOThread extends Thread {
    62     private Socket socket = null;
    63     private IOStrategy ios = null;
    64 
    65     public IOThread(IOStrategy ios) {
    66         this.ios = ios;
    67     }
    68 
    69     public boolean isIdle() {
    70         return socket == null;
    71     }
    72 
    73     public synchronized void setSocket(Socket socket) {
    74         this.socket = socket;
    75         notify();//唤醒
    76     }
    77 
    78     public synchronized void run() {
    79         while (true) {
    80             try {
    81                 wait();//等待到setSocket执行notify()后,调用service()
    82                 ios.service(socket);
    83                 socket = null;//service()结束后,套接字置为空
    84             } catch (Exception e) {
    85                 e.printStackTrace();
    86             }
    87         }
    88     }
    89 };
    View Code

    IOStrategy.java

     1 /*
     2     IOStrategy.java
     3 */
     4 
     5 import java.net.*;
     6 
     7 /*
     8     提供协议策略定义
     9 */
    10 
    11 public interface IOStrategy
    12 {
    13     public void service(Socket socket);
    14 }
    View Code

    NwServer.java

     1 /*
     2     NwServer.java
     3 */
     4 
     5 import java.net.*;
     6 
     7 /*
     8     实现网络通信,可以服务于任何应用,没有提供协议,
     9     也就是说NwServer可以适用于任何协议。
    10 */
    11 
    12 public class NwServer
    13 {
    14     private int port = 4321;  //没有处理端口
    15     
    16     public NwServer(IOStrategy io, int port) throws Exception {
    17         //它只负责接受客户端的连接请求,建立网络建立(socket连接)
    18         //然后将连接提交给协议处理程序。
    19         
    20         this.port = port;
    21 
    22         ServerSocket server = new ServerSocket(port);
    23         System.out.println("FTServer is ready");
    24 
    25         while(true)
    26         {
    27             //接受客户端的连接请求
    28             Socket socket = server.accept();
    29             
    30             //获取客户端地址
    31             InetAddress ia = socket.getInetAddress();
    32             System.out.println(ia.getHostName() + "(" + ia.getHostAddress() + ") connected."); 
    33             
    34             //将连接提交给协议处理程序
    35             io.service(socket);
    36         }
    37     }
    38 }
    View Code

    server.properties配置文件:

    1 share=C:\_Server
    2 port=4321
    View Code

    效果展示:

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

    服务器:

    客户端:

    1.编译

     

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

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

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

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

      ·choice输入q或Q则退出

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

    ·直接上传文件名

    ·上传文件夹

     

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

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

  • 相关阅读:
    Evaluate Reverse Polish Notation
    openstack VM可以ping外部网络,但是外部网络ping不通VM
    Object Storage(Swift)安装过程——Havana
    完数c实现
    ubuntu用户及用户组文件信息
    Ubuntu12.04安装java以及Eclipse和Tomcat
    Ubuntu 12.04 Server OpenStack Havana多节点(OVS+GRE)安装
    ERROR:the server has either erred or is incapable of performing the requested operation
    openMPI小集群安装
    分片传输——send和recv函数
  • 原文地址:https://www.cnblogs.com/lca1826/p/6431735.html
Copyright © 2011-2022 走看看