sockets, java sending files server client - java

I want to send a file through a socket. The "server" is sitting on another computer than mine and the client in another computer as well. The file can go to and fro server and client but only in their current directory. The approach i have taken up to now is by using a file input stream and writing the file on a file output stream neverthelees this doesnt work as far as i understand.. Is there another way to send files through sockets?
Here is my code what could be wrong here?
public class Copy {
private ListDirectory dir;
private Socket socket;
public Copy(Socket socket, ListDirectory dir) {
this.dir = dir;
this.socket = socket;
}
public String getCopyPath(String file) throws Exception {
String path = dir.getCurrentPath();
path += "\\" + file;
return path;
}
public void copyFileToClient(String file, String destinationPath)
throws Exception {
byte[] receivedData = new byte[8192];
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(getCopyPath(file)));
String findDot = file;
String extension = "";
for (int i = 0; i < findDot.length(); i++) {
String dot = findDot.substring(i, i + 1);
if (dot.equals(".")) {
extension = findDot.substring(i + 1);
}
}
if (extension.equals("")) {
extension = "txt";
}
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(new File(destinationPath + "\\"
+ "THECOPY" + "." + extension)));
int len;
while ((len = bis.read(receivedData)) > 0) {
bos.write(receivedData, 0, len);
}
// in.close();
bis.close();
// output.close();
bos.close();
}
// public static void main(String args[]) throws Exception {
// Copy copy = new Copy();
// System.out.print(copy.getCopyPath("a"));
// }
}
And some client code :
...
DataOutputStream outToServer = new DataOutputStream(
clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
boolean exit = false;
else if (sentence.length() > 3 && sentence.substring(0, 3).equals("get")) {
String currPath = dir.getCurrentPath();
outToServer.writeBytes(sentence + "_" + currPath + "\n");
} else {
...

Your copyFileToClient method uses a FileInputStream and FileOutputStream directly, i.e. it does not transfer anything to/from the client at all, only from one local file to another. This is fine if you want to manage remotely files on the server, but does not help for sending data between different computers.
You have to somehow send the data through the OutputStream/InputStream of the Socket - i.e. use the FileInputStream at the sending side and the FileOutputStream at the receiving one.

Related

creating Socket to connect to windows 10 machine from Raspberry pi 4 Raspbian does not work (Java)

I have a Raspberry pi 4 with Raspbian installed, and I have a computer with Windows 10 installed.I wrote two functions one send a file and the other one receive the file.
when I run this function that sends a file on the raspberry pi 4:
public static void sendFile(String fileName, String ip)
{
BufferedOutputStream outputStream = null;
PrintWriter writer = null;
BufferedReader reader = null;
FileInputStream filein = null;
File file = new File(fileName);
if (!file.exists())
{
System.out.println(fileName + " does not exist");
return;
}
try
{
Socket socket = new Socket(ip, port);
outputStream = new BufferedOutputStream(socket.getOutputStream());
writer = new PrintWriter(socket.getOutputStream());
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
filein = new FileInputStream(file);
long fileSize = file.length();
writer.println(fileName); // sending file name
writer.println(fileSize); // sending file size in bytes
writer.flush();
byte[] dataBuffer = new byte[1024];
int numberOfReadBytes = 0; // the number of read bytes for each read() function call
System.out.println("Entering the loop");
for(long i = 0; i < fileSize && numberOfReadBytes > -1;)
{
numberOfReadBytes = filein.read(dataBuffer); // read read() function returns the number of bytes tha has been assigned to the array or -1 if EOF(end of file) is reached
outputStream.write(dataBuffer, 0, numberOfReadBytes); // writing the bytes in dataBuffer from index 0 to index numberOfBytes
i += numberOfReadBytes;
}
outputStream.flush();
System.out.println(fileName + " sent to " + ip);
String status = reader.readLine();
System.out.println("Status: " + status + "\t file save successfully on the other machine.");
}
catch(IOException ioe)
{
System.err.println("Status: 0\n" + ioe.getMessage());
}
finally // closing streams
{
try
{
outputStream.close();
reader.close();
writer.close();
filein.close();
}
catch (IOException ioe)
{
System.err.println("Error closing the connection.");
}
}
}
it stops at this line Socket socket = new Socket(ip, port);
and this is the other function that runs on windows 10
public static void receiveFile()
{
// 1- read the file name
// 2- read the size of the file
// 3- read the file and write it
ServerSocket server = null;
Socket socket = null;
BufferedReader reader = null;
BufferedInputStream inputStream = null;
FileOutputStream fileout = null;
PrintWriter writer = null;
try
{
server = new ServerSocket(9999);
socket = server.accept();
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
inputStream = new BufferedInputStream(socket.getInputStream());
writer = new PrintWriter(socket.getOutputStream());
String fileName = reader.readLine(); // reading file name
long fileSize = Long.parseLong(reader.readLine()); // reading file size
System.out.println(fileSize);
// reading file data and write the data
File file = new File(fileName);
fileout = new FileOutputStream(file);
for (long i = 0; i < fileSize; ++i)
{
fileout.write(inputStream.read());
System.out.println(i);
}
fileout.flush();
fileout.close();
writer.println('1');
System.out.println("Status: 1");
System.out.println(fileName+ " is saved successfully");
}
catch (IOException ioe)
{
System.err.println("Status: 0");
System.err.println(ioe.getMessage());
}
finally
{
try
{
reader.close();
inputStream.close();
}
catch(IOException ioe)
{
System.err.println("Error closing connection\n" + ioe.getMessage());
}
}
}
I think windows 10 firewall blocks connection, but I am not sure.
It turns out it was the firewall blocking connection from the raspberry pi

FileOutputStream writing out 0 bytes [duplicate]

This question already has answers here:
Java multiple file transfer over socket
(3 answers)
Closed 5 years ago.
I'm trying to send a file through Java sockets from one program to the other. My code is based off of this question. The issue is that on the Ubuntu machine hosting the server, the file sent over is 0 bytes in size. The code has worked on a local connection on my Windows laptop, so perhaps the issue has to do with the remote connection?
Server code:
int g = Integer.parseInt(in.readLine());
if(g > -1) {
InputStream fIn = client.getInputStream();
for(int i = 0; i < g; i++) {
String name = in.readLine();
byte[] bytes = new byte[16*1024];
File f = new File("plugins/" + name + ".jar");
if(!f.exists()) f.createNewFile();
FileOutputStream fOut = new FileOutputStream(f);
int count;
while ((count = fIn.read(bytes)) >= 0) {
fOut.write(bytes, 0, count);
}
fOut.flush();
fOut.close();
}
System.out.println("[" + client.getRemoteSocketAddress().toString() + "] added " + g + " new plugins.");
client.close();
}else{
client.close();
}
Client code:
JFileChooser fd = new JFileChooser("C:\\");
fd.setFileSelectionMode(JFileChooser.FILES_ONLY);
fd.setMultiSelectionEnabled(true);
fd.setFileFilter(new FileNameExtensionFilter(null,"jar"));
int r = fd.showOpenDialog(null);
if(r == JFileChooser.APPROVE_OPTION) {
File[] files = fd.getSelectedFiles();
OutputStream fOut = sock.getOutputStream();
out.println(files.length);
for(File f : files) {
out.println(f.getName().split("\\.")[0]);
byte[] bytes = new byte[16 * 1024];
FileInputStream fIn = new FileInputStream(f);
int count;
while ((count = fIn.read(bytes)) >= 0) {
fOut.write(bytes, 0, count);
}
fIn.close();
}
}else{
out.println(-1);
}
sock.close();
As said in the comments there are different issues in you code.
To recognise the end of single file you can simply add the file size after the filename separated by a Semicolon;
out.println(f.getName().split("\\.")[0] + "; size" + f.length());
On the Server side you accumulate the file size read / written stop read ing the content of the file close it and read the next line (filename / file size).
As said in the comments there are different issues.
You use fIn and fOut which is not clear how they are defined.
On the client side you use fOut while the Socket OutputStream is named 'out'.
Similar thing on the server side. You read the number of files from in but afterwards you get the InputStream (again?) from the Socket and use that as fIn. Depending on your in that may or may not work.
Also reading a line from via readLine from an InputStream and also binary content is not that trivial. In my example code I'm using the DataInputStream for that even the readLine method is deprecated.
The Example also uses the "try with resources" Syntax to ensure that all resources (Streams, Sockets) get closed in the case of an Exception.
The Example does not show how to deal with the file size on the server side That's up to you.
The example is completely runnable on a single machine and shows how to copy a single file via socket based on your code.
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class ClientServerSocketExample {
private static class Server {
public void run() throws IOException {
try (ServerSocket serverSocket = new ServerSocket(41000, 10, InetAddress.getLocalHost())) {
try (Socket client = serverSocket.accept()) {
try (DataInputStream in = new DataInputStream(client.getInputStream())) {
int g = Integer.parseInt(in.readLine());
if(g > -1) {
for(int i = 0; i < g; i++) {
String[] filenameAndSize = in.readLine().split(";");
String name = filenameAndSize[0];
byte[] bytes = new byte[16*1024];
File f = new File("/tmp/" + name + ".jar");
if(!f.exists()) f.createNewFile();
try (FileOutputStream fOut = new FileOutputStream(f)) {
int count;
while ((count = in.read(bytes)) >= 0) {
fOut.write(bytes, 0, count);
}
fOut.flush();
}
}
System.out.println("[" + client.getRemoteSocketAddress().toString() + "] added " + g + " new plugins.");
}
}
}
}
}
}
private static class Client {
public void run() throws IOException {
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(InetAddress.getLocalHost(), 41000) );
sendFiles(socket);
}
}
private static void sendFiles(Socket sock) throws IOException {
File[] files = new File[]{new File("some.jar")};
OutputStream fOut = sock.getOutputStream();
PrintStream out = new PrintStream(fOut);
out.println(files.length);
for(File f : files) {
out.println(f.getName().split("\\.")[0] + "; size" + f.length());
byte[] bytes = new byte[16 * 1024];
try (FileInputStream fIn = new FileInputStream(f)) {
int count;
while ((count = fIn.read(bytes)) >= 0) {
out.write(bytes, 0, count);
}
out.flush();
}
}
}
}
public static void main(String ... args) throws IOException, InterruptedException {
new Thread(new Runnable() {
#Override
public void run() {
try {
new Server().run();
} catch (IOException ioe) {
System.out.println(ioe);
}
}
}).start();
System.out.println("Waiting for the Server to come up");
Thread.sleep(500);
new Client().run();
}
}
There may be an issue in this solution when the client sends a \r as new line separator and the file starts with \n. The server may count the \n as part of the line separator and the file will be corrupt (one byte will be missing).

Send file via socket - buffer size [duplicate]

This question already has answers here:
Java multiple file transfer over socket
(3 answers)
Closed 5 years ago.
TL;DR: How do I send (with a single connection) file, its size and its name. All examples in the internet send a file alone.
Server:
public class Server {
private static int PORT = 6667;
private ServerSocket serverSocket;
public void run() throws IOException {
System.out.println("Opening server");
serverSocket = new ServerSocket(PORT);
while(true) {
try(Socket incomingSocket = serverSocket.accept()) {
System.out.println("Accepted connection: " + incomingSocket);
incomingSocket.setSoTimeout(2000); // Don't let scanner block the thread.
InputStream inputStream = incomingSocket.getInputStream();
Scanner scanner = new Scanner(inputStream);
String command = "";
if(scanner.hasNextLine())
command = scanner.nextLine();
if(command.equals("update")) {
File file = new File("abc.txt");
sendFile(incomingSocket, file);
}
else {
// ...
System.out.println("Another command");
}
}
}
}
private void sendFile(Socket socket, File file) throws IOException {
byte[] bytes = new byte[(int)file.length()];
FileInputStream fileInputStream = new FileInputStream(file);
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
bufferedInputStream.read(bytes, 0, bytes.length);
OutputStream outputStream = socket.getOutputStream();
PrintWriter writer = new PrintWriter(outputStream, true);
writer.println(file.length());
writer.println(file.getName());
System.out.println("Sending " + file.getName() + "(" + bytes.length + " bytes) to " + socket);
outputStream.write(bytes, 0, bytes.length);
outputStream.flush();
System.out.println("File sent");
}
public void stopRunning() {
try {
serverSocket.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
Client:
public class Client {
private static String HOST = "localhost";
private static int PORT = 6667;
public void run() throws IOException {
Socket socket = new Socket(HOST, PORT);
System.out.println("Connecting...");
OutputStream outputStream = socket.getOutputStream();
PrintWriter writer = new PrintWriter(outputStream, true);
writer.println("update"); // Example command which will determine what server sends back
receiveFile(socket);
socket.close();
}
private void receiveFile(Socket socket) throws IOException {
InputStream inputStream = socket.getInputStream();
int size = 16384;
String name = "example.txt";
Scanner scanner = new Scanner(inputStream);
size = Integer.parseInt(scanner.next());
name = scanner.next();
FileOutputStream fileOutputStream = new FileOutputStream(name);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
byte[] buffer = new byte[size];
int bytesRead, totalRead = 0;
while ((bytesRead = inputStream.read(buffer, 0, buffer.length)) != -1) {
totalRead += bytesRead;
bufferedOutputStream.write(buffer, 0, bytesRead);
}
bufferedOutputStream.flush();
System.out.println("File " + name + " received. " + totalRead + " bytes read");
bufferedOutputStream.close();
fileOutputStream.close();
}
I want my server to send a file to the client. It should also include the file's name and its size. Name because it's quite important and the size because I don't want to make a hardcoded buffer with a huge size.
Tried it with the code above. The client's "scanner part"
Scanner scanner = new Scanner(inputStream);
size = Integer.parseInt(scanner.next());
name = scanner.next();
works just okay, but the file is not received. inputStream.read(buffer, 0, buffer.length) never reads the remaining bytes from the stream.
If i comment out the scanner part, the bytes are read correctly(size and name information + file itself)
So, the question is, how do I send it with a single connection? Or should I make 2 separate connections, in the first one asking for size and file name and sending the file in the second one?
Scanner is good for text-based work.
One way to do what you want is using DataInputStream and DataOutputStream. Only one connection is needed:
public void send(File file, OutputStream os) throws IOException {
DataOutputStream dos = new DataOutputStream(os);
// writing name
dos.writeUTF(file.getName());
// writing length
dos.writeLong(file.length());
// writing file content
... your write loop, write to dos
dos.flush();
}
public void receive(InputStream is) throws IOException {
DataInputStream dis = new DataInputStream(is);
String fileName = dis.readUTF();
long fileSize = dis.readLong();
// reading file content
... your read loop, read from dis
}

Code that download empty file and supposed not to

I have this part of function where it supposed to download file like pdf from server and store in new directory. It does do this but an empty pdf or text file.How to fix it.
`File urlfile = new File(host + "/" + path);
urlfile.getParentFile().mkdirs();
// create outputstream for request and inputstream for data
// download
FileOutputStream outS = new FileOutputStream(urlfile);
DataInputStream instream = new DataInputStream(newsocket.getInputStream());
// get rid of head part to get to actual file
String l = null;
String lastmodtime = null;
boolean done = false;
while (!(l = DAA.readLine()).equals("")) {
if (!done && l.contains("Last-Modified:")) {
lastmodtime = l.substring(l.indexOf(' ') + 1, l.length());
done = true;
System.out.println(l);
}
}
// read in bytes to correct file name
try {
byte[] inbytes = new byte[16384];
int input;
while ((input = instream.read(inbytes)) != -1) {
outS.write(inbytes, 0, input);
}
}`
You can try this simple code if you want to create a copy of the file or you can even use apache commons io (FileUtils.copyFile(source, dest)) for java copy file operation.
private static void copyFileUsingStream(File source, File dest)
throws IOException {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(source);
os = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
} finally {
is.close();
os.close();
}
}

Java sending file is always 8 bytes less when received

I have two problems with my java server-client file communication,
I have the CLIENT sends files over to the server and the SERVER receives the files.
My 2 issues are:
1) whenever i send a file, it is 8 bytes less (i do not know why)
2) the file transfer is not complete (with 8 bytes less) unless i close the socket, which i do not want. i want my connection to be persistent, so how can i send a EOF from the client to the server.
here is my client who sends files
public void sendFiles(String file) {
try {
File myFile = new File(file);
long length = myFile.length();
byte[] buffer = new byte[8192];
System.out.println(length);
FileInputStream in = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(in);
BufferedOutputStream outF = new BufferedOutputStream(sock.getOutputStream());
out.print("%SF%" + length + "$" + myFile.getName() + "#");
out.flush();
int count;
while ((count = in.read(buffer)) > 0) {
outF.write(buffer, 0, count);
}
outF.flush();
in.close();
bis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
SERVER who receives files.
I'm passing the name and the length of the file but only using the name of the file. however, i don't know if i need to use the length of the file or not, in case of EOF or something. Please advice
Also, The code hangs in
while ((count = this.sock.getInputStream().read(buffer)) > 0) {
due to no EOF which i do not know how to implement
public void recvFile(String fileName, int length) {
try {
byte[] buffer = new byte[8192];
FileOutputStream outF = new FileOutputStream("/Users/Documents" +fileName);
BufferedOutputStream bos = new BufferedOutputStream(outF);
int count = length;
while ((count = this.sock.getInputStream().read(buffer)) > 0) {
bos.write(buffer, 0, count);
}
bos.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
UPDATE: I have removed the flush() as advised that it is not needed. Also, i have tested this code in a different class and it worked but it doesn't work here with client-server chat. Could anyone tell me why?
Any help or hints would be appreciated.
Thank you.
I would suggest to you send the file size first and/or properties of the file... You can try HTTP which is wide use for this task...
Another suggestion would be for you to open another connection on other TCP port just to send the file (this is actually how FTP sends files)
I suspect the problem you have is in code you haven't shown.
In this example you can send multiple messages or files over the same stream.
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.SocketChannel;
/**
* Created by peter on 1/25/15.
*/
public class DataSocket implements Closeable {
private final Socket socket;
private final DataOutputStream out;
private final DataInputStream in;
public DataSocket(Socket socket) throws IOException {
this.socket = socket;
this.out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
this.in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
}
#Override
public void close() throws IOException {
out.flush();
socket.close();
}
// message format is length as UTF-8 encoded name, 32-bit int followed by data.
public void writeMessage(String description, byte[] bytes) throws IOException {
out.writeUTF(description);
out.writeInt(bytes.length);
out.write(bytes);
out.flush();
}
public byte[] readMessage(String[] description) throws IOException {
description[0] = in.readUTF();
int length = in.readInt();
byte[] bytes = new byte[length];
in.readFully(bytes);
return bytes;
}
public void writeFile(File file) throws IOException {
long length = file.length();
if (length > Integer.MAX_VALUE) throw new IllegalArgumentException("length=" + length);
out.writeUTF(file.toString());
out.writeInt((int) length);
byte[] buffer = new byte[(int) Math.min(length, 32 * 1024)];
try (FileInputStream fis = new FileInputStream(file)) {
for (int len; (len = fis.read(buffer)) > 0; ) {
out.write(buffer, 0, len);
}
}
out.flush();
}
public void readFile(File dir) throws IOException {
String fileName = in.readUTF();
int length = in.readInt();
byte[] buffer = new byte[(int) Math.min(length, 32 * 1024)];
try (FileOutputStream fos = new FileOutputStream(new File(dir, fileName))) {
while (length > 0) {
int len = in.read(buffer);
fos.write(buffer, 0, len);
length -= len;
}
}
}
// todo convert to a unit test
public static void main(String[] args) throws IOException {
// port 0 opens on a random free port.
ServerSocket sc = new ServerSocket(0);
DataSocket ds1 = new DataSocket(new Socket("localhost", sc.getLocalPort()));
DataSocket ds2 = new DataSocket(sc.accept());
sc.close();
// now ds1 and ds2 are connected.
File f = File.createTempFile("deleteme","");
f.deleteOnExit();
try (FileOutputStream fos = new FileOutputStream(f)) {
fos.write(new byte[10001]);
}
// send a request
ds1.writeMessage("Send me the file", new byte[0]);
String[] desc = { null };
byte[] data = ds2.readMessage(desc);
if (!desc[0].equals("Send me the file")) throw new AssertionError();
// return a response
ds2.writeFile(f);
f.delete();
if (f.exists()) throw new AssertionError();
ds1.readFile(new File(""));
if (f.length() != 10001) throw new AssertionError("length="+f.length());
ds1.close();
ds2.close();
System.out.println("Copied a "+f.length()+" file over TCP");
}
}

Categories

Resources