Всем добрый день. Возникла такая ситуация: нужно от сервера передать файл изображения клиенту. Непродолжительный поиск по всемирной паутине результатов не дал, и я решил написать свой класс, который мог бы справиться с поставленной задачей. В итоге получилось следующее:
/**
* Класс, который задумывался для передачи изображения, но походу им можно
* передавать любые файлы, желательно небольшие
* @author Murashko Arthur
*/
public class ImageFileTransfer {
private static int bufferSize = 1024;
/**
* Данный метод передает файл клиенту, для того, чтобы принять этот файл
* нужно вызвать метод ImageFileTransfer.read(...)
* @param socket сокет клиента
* @param imageFile файл, который нужно передать
*/
public static void send(Socket socket, File imageFile) {
FileInputStream inputFile = null;
ObjectOutputStream out = null;
ImagePackage imagePackage = null;
byte [] bytes = new byte[bufferSize];
int length = 0;
try {
try {
inputFile = new FileInputStream(imageFile);
out = new ObjectOutputStream(socket.getOutputStream());
while (true) {
length = inputFile.read(bytes, 0, bufferSize);
if (length == -1) {
imagePackage = new ImagePackage(bytes, 0, true);
out.writeObject(imagePackage);
break;
}
imagePackage = new ImagePackage(bytes, length, false);
out.writeObject(imagePackage);
out.flush();
}
} finally {
inputFile.close();
System.out.println("Файл передан.");
}
} catch (FileNotFoundException ex) {
Logger.getLogger(ImageFileTransfer.class.getName()).log(
Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(ImageFileTransfer.class.getName()).log(
Level.SEVERE, null, ex);
}
}
/**
* Данный метод сохраняет файл, посланный сервером в нужном месте
* @param socket сокет клиента
* @param name полное имя, с которым хотим сохранить файл
* @return объект класса File ассоциированный с переданным файлом
*/
public static File read(Socket socket, String name) {
File imageFile = null;
FileOutputStream outImgFile = null;
ObjectInputStream input = null;
ImagePackage imagePackage = null;
try {
try {
imageFile = new File(name);
outImgFile = new FileOutputStream(imageFile);
input = new ObjectInputStream(socket.getInputStream());
imagePackage = (ImagePackage) input.readObject();
while (!imagePackage.isFinish()) {
outImgFile.write(imagePackage.getBytes(), 0,
imagePackage.getLength());
imagePackage = (ImagePackage) input.readObject();
}
} finally {
outImgFile.close();
}
} catch (IOException ex) {
Logger.getLogger(ImageFileTransfer.class.getName()).log(
Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(ImageFileTransfer.class.getName()).log(
Level.SEVERE, null, ex);
}
return imageFile;
}
private static class ImagePackage implements Serializable {
private boolean finish;
private int length;
private byte[] bytes;
public ImagePackage(byte[] b, int length, boolean f) {
this.length = length;
bytes = b.clone();
finish = f;
}
public boolean isFinish() {
return finish;
}
public byte[] getBytes() {
return bytes;
}
public int getLength() {
return this.length;
}
}
}
Как видно из данного кода, у меня передаются объекты. Вот данный нюанс и мучает меня больше всего. Изначально я просто методами read и write соотвественно классов InputStream и OutputStream передавал байты моего файла, причем порциями по 1024 байта, но я не мог отследить на клиенте, когда приходит последняя порция данных - у меня просто метод read блокировал поток и ждал следующих данных.
Так вот после всего, хотелось бы узнать у Вас, есть ли какие-то встроенные средства позволяющие передавать файлы через сокет в Java, а также более красивое решение данной проблемы. И, пожалуйста, не пишите об избыточности кода, сам знаю что и где.