Возобновление загрузки файла в Java Socket - PullRequest
0 голосов
/ 04 января 2019
package experiments; 

import java.io.*;

 import java.net.Socket; 
/** * * @author User */ 

/*THE CLIENT*/ public class UploadManager { 

public static void setup(String address, int port,String path){ 

try( Socket s = new Socket(address,port); OutputStream out = s.getOutputStream(); InputStream in = s.getInputStream(); DataOutputStream dos = new DataOutputStream(out); 
DataInputStream dis = new DataInputStream(in); )

{ 
/** * send file name and size to server */ 
System.out.println("processing file now"); 

File from = new File(path); 

if(from.exists() && from.canRead()){ 

String FILENAME = from.getName(); 

long FILESIZE = from.length();
 // String FILEHASH 

 /** * write all ,2 * to SERVER */ dos.writeLong(FILESIZE); dos.writeUTF(FILENAME);
 //dos.writeUTF(FILEHASH); 
dos.flush(); 

/** * what does SERVER HAS TO SAY? */

 String RESPONSE_FROM_SERVER_1 =dis.readUTF();
 if(RESPONSE_FROM_SERVER_1 . equalsIgnoreCase("SEND")){ 
uploadFresh(from,dos); 
}   
    /** * in case there was an interruption we need * resume from an offset. */ 

        if(RESPONSE_FROM_SERVER_1 . equalsIgnoreCase("RESUME")){

 /** * length already sent */

 System.out.println("resuming upload"); 

String LENGTH_ALREADY_READ =dis.readUTF(); 

long OFF_SET = Long.parseLong(LENGTH_ALREADY_READ); 

/** * get the file name so we know the exact file */ 

String FILE_REAL_NAME = dis.readUTF(); 

resume(FILE_REAL_NAME,OFF_SET,dos);
 } 
}else{ System.out.println("Couldn't read: err"); 

} 

}catch(Exception ex){ 
ex.printStackTrace(); 
}
 }
 /** the resume method **/ 

private static void resume(String FILE_REAL_NAME,long OFF_SET,DataOutputStream to)throws Exception{ 

/** * copy from the stream or disk to server */ 

FileInputStream reader = null; 

try{
 reader = new FileInputStream(new File("c:\\movies\\hallow.mp4",FILE_REAL_NAME)); byte[] size = new byte [8192]; 

int COUNT_BYTES_READ ; reader.skip(OFF_SET);

//skip the length already written

 while( (COUNT_BYTES_READ = reader.read(size)) >0{ 

to.write(size); 
to.flush();
 } 
}finally{ 
if( reader != null ) reader.close();

 to.close(); 

}
 } 

/** and the normal send method which works as expected **/ 

private static void uploadFresh(File from, DataOutputStream to)throws Exception{

 /** * copy from the stream or disk to server */ 
FileInputStream reader = null;
 try{ 
reader = new FileInputStream(from); 
byte[] size = new byte [1024];
 int COUNT_BYTES_READ ; 

while( (COUNT_BYTES_READ = reader.read(size)) >0){

 to.write(size,0,COUNT_BYTES_READ); to.flush(); 
} 
}finally{ 
if( reader != null ) reader.close();

 to.close(); 
}
 } 
}

// СЕРВЕР

public class UserServer { 
String ip_Adress; 
int Port; 
ServerSocket ss; 
String path;

public UserServer(String ip_Adress,int Port ){
 this.Port =Port; this.ip_Adress = ip_Adress; this. path = path;
 } 

public void startserver() throws IOException{
 FileOutputStream fos =null; 
// String realhash; 
out.println("starting server"); 

this.ss= new ServerSocket(Port);
 out.println("starting server on port"+Port); out.println("waiting for client conection......"); 

Socket visitor = this.ss.accept(); 

out.println("1 User connected to port");

 /** 
* reading file name and size from upload 
*/ 
try( OutputStream ot =visitor.getOutputStream(); InputStream in = visitor.getInputStream(); DataOutputStream dos = new DataOutputStream(ot); DataInputStream dis = new DataInputStream(in); ){ 

System.out.println("processing debug"); 
long FILE_SIZE = dis.readLong();

 System.out.println(FILE_SIZE+"processing"); 

String FILE_NAME = dis.readUTF(); System.out.println(FILE_NAME+"processing");

 //String FILEHASH = dis.readUTF(); // System.out.println(FILEHASH+"processing"); 

File file = new File("c:\\aylo\\"+FILE_NAME); 

/** * what do We Have TO Say? */
 if(file.exists()){ 
long SIZE = file.length(); 
if(SIZE<FILE_SIZE){ 


String RESUME = "RESUME";   

//tell client to resume the upload
 dos.writeUTF(RESUME); 

/*sending the resuming length in*/ string String size = String.valueOf(SIZE);

 dos.writeUTF(size); 
dos.flush();

 fos=new FileOutputStream(file,true);
//append to exisiting file 

byte[] b = new byte [1024]; int COUNT_BYTES_READ ;
 while( (COUNT_BYTES_READ = dis.read(b)) >0){ 
fos.write(b);
 fos.flush();
} 
} 
} else{ 
} 
if(!file.exists()){
 file.getParentFile().mkdirs();
 file.createNewFile();

 String SEND = "SEND";
 dos.writeUTF(SEND);
 dos.flush();
 fos=new FileOutputStream(file); 

byte b[]=new byte[1024];

 int s;
 while((s=dis.read(b))>0){ 
fos.write(b,0,s); fos.flush(); System.out.println(s+"processing"); 
} 

} 
System.out.println("i'm done reading ");



}catch(Exception ex){ 

ex.printStackTrace();

 }finally{
 fos.close(); 
if(this.ss!=null) this.ss.close(); 
} 
}   

// основной

public static void main(String []arg){

     UserServer us = new UserServer("localhost", 2089);
     us.startserver();      

    //start client

 UploadManager.setup("localhost", 2089, ("c:\\movies\\hallow.mp4")); 
    }
     }

Я искал и искал большинство форумов и ОС по этому поводу и ничего не нашел. Что я пытаюсь сделать, это узнать или выяснить, как я могу возобновить файл, прерванный при загрузке через сокет Java. Прямо сейчас мой код частично работает, но всегда есть разрыв или разрыв, который, как я предполагал, вызван конструктором new FileOutputStream (from, true); Может кто-нибудь, пожалуйста, проверьте мои методы и помогите указать на мои ошибки, пример демонстрационного кода тоже будет хорошо. Спасибо!

1 Ответ

0 голосов
/ 04 января 2019

Пожалуйста, ознакомьтесь с Java соглашением об именах переменных; Мне потребовалось много времени, чтобы найти вашу проблему, и во многом это связано с тем, что ваш код выглядит незнакомым. Кроме того, действительно, проверьте ваши имена. Наименование байтового буфера для передачи байтов 'size' похоже на наименование вашей любимой кошки 'horse'. Это может вызвать путаницу.

Проблема: у вас есть несколько мест, где вы делаете это:

   byte[] buffer = new byte[8192];
   int bytesRead = networkIn.read(buffer);
   fileOut.write(buffer);

и это неверно. Вызов «write» запишет весь буфер, все 8192 байта, даже если на самом деле было прочитано менее 8192 байтов. Что вам нужно сделать, это:

   byte[] buffer = new byte[8192];
   int bytesRead = networkIn.read(buffer);
   fileOut.write(buffer, 0, bytesRead);

NB. Возможно, в вашем коде больше ошибок; вышеприведенный пример определенно вызывает проблемы и объясняет, почему операция возобновления приводит к повреждению файла.

...