Android下使用TCP/IP协议实现断点上传


0.使用http协议是不能实现断点上传的,对于文件大小不一,与实际需求可以使用Socket断点上传

1.上传原理:Android客户端发送上传文件头字段给服务器,服务器判断文件是否在服务器上,文件是否有上传的记录,若是文件不存在,服务器则返回一个id(断点数据)通知客户端从什么位置开始上传,客户端开始从获得的位置开始上传文件

2.实例演示

(0)服务器端代码

  1. public class FileServer   
  2. {  
  3.      //线程池   
  4.      private ExecutorService executorService;  
  5.      //监听端口   
  6.      private int port;  
  7.      //退出   
  8.      private boolean quit = false;  
  9.      private ServerSocket server;  
  10.      //存放断点数据   
  11.      private Map<Long, FileLog> datas = new HashMap<Long, FileLog>();  
  12.        
  13.      public FileServer(int port)  
  14.      {  
  15.          this.port = port;  
  16.          //创建线程池,池中具有(cpu个数*50)条线程   
  17.          executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 50);  
  18.      }  
  19.        
  20.      /** 
  21.       * 退出 
  22.       */  
  23.      public void quit()  
  24.      {  
  25.         this.quit = true;  
  26.         try   
  27.         {  
  28.             server.close();  
  29.         }   
  30.         catch (IOException e)   
  31.         {  
  32.             e.printStackTrace();  
  33.         }  
  34.      }  
  35.        
  36.      /** 
  37.       * 启动服务 
  38.       * @throws Exception 
  39.       */  
  40.      public void start() throws Exception  
  41.      {  
  42.          //实现端口监听   
  43.          server = new ServerSocket(port);  
  44.          while(!quit)  
  45.          {  
  46.              try   
  47.              {  
  48.                Socket socket = server.accept();  
  49.                //为支持多用户并发访问,采用线程池管理每一个用户的连接请求   
  50.                executorService.execute(new SocketTask(socket));  
  51.              }   
  52.              catch (Exception e)   
  53.              {  
  54.                  e.printStackTrace();  
  55.              }  
  56.          }  
  57.      }  
  58.        
  59.      private final class SocketTask implements Runnable  
  60.      {  
  61.         private Socket socket = null;  
  62.         public SocketTask(Socket socket)   
  63.         {  
  64.             this.socket = socket;  
  65.         }  
  66.           
  67.         @Override  
  68.         public void run()   
  69.         {  
  70.             try   
  71.             {  
  72.                 System.out.println("accepted connection "+ socket.getInetAddress()+ ":"+ socket.getPort());  
  73.                 //这里的输入流PushbackInputStream可以回退到之前的某个点开始进行读取   
  74.                 PushbackInputStream inStream = new PushbackInputStream(socket.getInputStream());  
  75.                 //得到客户端发来的第一行协议数据:Content-Length=143253434;filename=xxx.3gp;sourceid=   
  76.                 //如果用户初次上传文件,sourceid的值为空。   
  77.                 String head = StreamTool.readLine(inStream);  
  78.                 System.out.println(head);  
  79.                 if(head!=null)  
  80.                 {  
  81.                     //下面从协议数据中提取各项参数值   
  82.                     String[] items = head.split(";");  
  83.                     String filelength = items[0].substring(items[0].indexOf("=")+1);  
  84.                     String filename = items[1].substring(items[1].indexOf("=")+1);  
  85.                     String sourceid = items[2].substring(items[2].indexOf("=")+1);        
  86.                     //生产资源id,如果需要唯一性,可以采用UUID   
  87.                     long id = System.currentTimeMillis();  
  88.                     FileLog log = null;  
  89.                     if(sourceid!=null && !"".equals(sourceid))  
  90.                     {  
  91.                         id = Long.valueOf(sourceid);  
  92.                         //查找上传的文件是否存在上传记录   
  93.                         log = find(id);  
  94.                     }  
  95.                     File file = null;  
  96.                     int position = 0;  
  97.                     //如果上传的文件不存在上传记录,为文件添加跟踪记录   
  98.                     if(log==null)  
  99.                     {  
  100.                         String path = new SimpleDateFormat("yyyy/MM/dd/HH/mm").format(new Date());  
  101.                         //设置存放的位置与当前应用的位置有关   
  102.                         File dir = new File("file/"+ path);  
  103.                         if(!dir.exists()) dir.mkdirs();  
  104.                         file = new File(dir, filename);  
  105.                         //如果上传的文件发生重名,然后进行改名   
  106.                         if(file.exists())  
  107.                         {  
  108.                             filename = filename.substring(0, filename.indexOf(".")-1)+ dir.listFiles().length+ filename.substring(filename.indexOf("."));  
  109.                             file = new File(dir, filename);  
  110.                         }  
  111.                         save(id, file);  
  112.                     }  
  113.                     // 如果上传的文件存在上传记录,读取上次的断点位置   
  114.                     else  
  115.                     {  
  116.                         //从上传记录中得到文件的路径   
  117.                         file = new File(log.getPath());  
  118.                         if(file.exists())  
  119.                         {  
  120.                             File logFile = new File(file.getParentFile(), file.getName()+".log");  
  121.                             if(logFile.exists())  
  122.                             {  
  123.                                 Properties properties = new Properties();  
  124.                                 properties.load(new FileInputStream(logFile));  
  125.                                 //读取断点位置   
  126.                                 position = Integer.valueOf(properties.getProperty("length"));  
  127.                             }  
  128.                         }  
  129.                     }  
  130.                       
  131.                     OutputStream outStream = socket.getOutputStream();  
  132.                     String response = "sourceid="+ id+ ";position="+ position+ "/r/n";  
  133.                     //服务器收到客户端的请求信息后,给客户端返回响应信息:sourceid=1274773833264;position=0   
  134.                     //sourceid由服务生成,唯一标识上传的文件,position指示客户端从文件的什么位置开始上传   
  135.                     outStream.write(response.getBytes());  
  136.                     //   
  137.                     RandomAccessFile fileOutStream = new RandomAccessFile(file, "rwd");  
  138.                     //设置文件长度   
  139.                     if(position==0) fileOutStream.setLength(Integer.valueOf(filelength));  
  140.                     //移动文件指定的位置开始写入数据   
  141.                     fileOutStream.seek(position);  
  142.                     byte[] buffer = new byte[1024];  
  143.                     int len = -1;  
  144.                     int length = position;  
  145.                     //从输入流中读取数据写入到文件中   
  146.                     while( (len=inStream.read(buffer)) != -1)  
  147.                     {  
  148.                         fileOutStream.write(buffer, 0, len);  
  149.                         length += len;  
  150.                         Properties properties = new Properties();  
  151.                         properties.put("length", String.valueOf(length));  
  152.                         FileOutputStream logFile = new FileOutputStream(new File(file.getParentFile(), file.getName()+".log"));  
  153.                         //实时记录文件的最后保存位置   
  154.                         properties.store(logFile, null);  
  155.                         logFile.close();  
  156.                     }  
  157.                     //如果长传长度等于实际长度则表示长传成功   
  158.                     if(length==fileOutStream.length()) delete(id);  
  159.                     fileOutStream.close();                    
  160.                     inStream.close();  
  161.                     outStream.close();  
  162.                     file = null;  
  163.                       
  164.                 }  
  165.             }  
  166.             catch (Exception e)   
  167.             {  
  168.                 e.printStackTrace();  
  169.             }  
  170.             finally  
  171.             {  
  172.                 try  
  173.                 {  
  174.                     if(socket!=null && !socket.isClosed()) socket.close();  
  175.                 }   
  176.                 catch (IOException e)  
  177.                 {  
  178.                     e.printStackTrace();  
  179.                 }  
  180.             }  
  181.         }  
  182.      }  
  183.        
  184.      public FileLog find(Long sourceid)  
  185.      {  
  186.          return datas.get(sourceid);  
  187.      }  
  188.      //保存上传记录   
  189.      public void save(Long id, File saveFile)  
  190.      {  
  191.          //日后可以改成通过数据库存放   
  192.          datas.put(id, new FileLog(id, saveFile.getAbsolutePath()));  
  193.      }  
  194.      //当文件上传完毕,删除记录   
  195.      public void delete(long sourceid)  
  196.      {  
  197.          if(datas.containsKey(sourceid)) datas.remove(sourceid);  
  198.      }  
  199.        
  200.      private class FileLog{  
  201.         private Long id;  
  202.         private String path;  
  203.         public Long getId() {  
  204.             return id;  
  205.         }  
  206.         public void setId(Long id) {  
  207.             this.id = id;  
  208.         }  
  209.         public String getPath() {  
  210.             return path;  
  211.         }  
  212.         public void setPath(String path) {  
  213.             this.path = path;  
  214.         }  
  215.         public FileLog(Long id, String path) {  
  216.             this.id = id;  
  217.             this.path = path;  
  218.         }     
  219.      }  
  220. }   
  • 1
  • 2
  • 3
  • 4
  • 下一页

相关内容