fileinputstream

Mattepuffo's logo
Invio di file tramite socket in Java (2nd edition)

Invio di file tramite socket in Java (2nd edition)

In questo articolo avevo già parlato di come trasferire file tramite socket in Java.

Il problema però è che funziona solo se sia il client che il server stanno sulla stessa macchina.

Questo perchè ho fatto uso di oggetti File che sono solo una rappresentazione di un file o directory sul pc, ma che non sanno nulla circa il lror contenuto.

Se invece server e client devono stare su macchine diverse bisogna cambiare un pò la logica.

In sostanza il client deve leggere e inviare il file byte per byte; il server legge tutti i byte e li salva sul pc.

Non si può quindi usare File.

Questo è il client:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client {

private final String HOST = "host";
private final int PORT = 9977;

public static void main(String[] args) {
Client c = new Client();
c.sendFile();
}

private void sendFile() {
try {
Socket socket = new Socket(HOST, PORT);
FileInputStream fis = new FileInputStream("path/to/file");
OutputStream out = socket.getOutputStream();
byte[] buf = new byte[1024];
int read;
while ((read = fis.read(buf)) != -1) {
out.write(buf, 0, read);
}
fis.close();
out.close();
socket.close();
} catch (UnknownHostException ex) {
System.out.println(ex.getMessage());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}

In pratica usiamo FileInputStream per leggere il contenuto del file, e OutputStream per inviare i byte.

Mattepuffo's logo
Invio di file tramite socket in Java

Invio di file tramite socket in Java

Uno dei punti forti di Java, si sa, è il netoworking con le Socket.

Java mette disposizione parecchie classi e metodi per usarle; qui vi spiego tre semplici classi da usare per inviare file tramite esse:

  • una si occuperà della parte server
  • una del client
  • una di gestire il multi-thread

In verità le classi server e multi-threading sono strettamente collegate, mentre la parte client può anche stare separata (alias in un altro progetto).

Cominciamo col vedere la classe predisposta al multi-threading:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;

public class MTManager implements Runnable {

private final String DIR_SAVE = "path-file";
private Socket socket;

public MTManager(Socket socket) {
this.socket = socket;
}

public void run() {
try {
System.out.println("presa in carico nuova connessione da " + socket);
ObjectInputStream oin = new ObjectInputStream(socket.getInputStream());
File inFile = (File) oin.readObject();
File saveFile = new File(DIR_SAVE + "/" + inFile.getName()); // attenti al path, io sto Linux dove il separatore è /, mentre su Windows è \
save(inFile, saveFile);
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
try {
socket.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}

private void save(File in, File out) throws IOException {
System.out.println(" --ricezione file " + in.getName());
System.out.println(" --dimensione file " + in.length());
FileInputStream fis = new FileInputStream(in);
FileOutputStream fos = new FileOutputStream(out);
byte[] buf = new byte[1024];
int i = 0;
while ((i = fis.read(buf)) != -1) {
fos.write(buf, 0, i);
}
fis.close();
fos.close();
System.out.println(" --ricezione completata");
}
}

Questa classe serve per istanziare un nuovo server ad ogni connessione, sennò si dovrebbe aspettare la conclusione dell'operazione per cominciarne una nuova.