I'm trying to send multiple files from client to server using socket but when I click upload button it adds only one file second
copyFile()
is not suitable for network transmissions.You need to get rid of the two close()
calls inside of copyFile()
. On the client side, out.close()
is closing the socket after the 1st file has been sent. On the server side, InputStream.close()
is closing the socket after the 1st file has been received. It is the caller's responsibility to close the streams it passes to copyFile()
, it is not copyFile()
's responsibility.
More importantly, for each file the client wants to send, copyFile()
is not sending the file's byte count before sending the file's actual bytes, to indicate where each file ends and the next begins. So, on the server side, copyFile()
does not know when to stop reading from the inputStream
and will just keep reading endlessly until the connection is closed/broken.
As-is, copyFile()
may work for copying files from one folder to another on the local system, but it is not suitable for copying files over a TCP network.
Try this instead:
Client side:
try {
socket.bind(null);
socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
Log.d(TAG, "Client socket - " + socket.isConnected());
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
DataOutputStream dos = new DataOutputStream(bos);
dos.writeInt(fileUri.size());
for(String file : fileUri)
{
//long length = file.length();
//dos.writeLong(length);
String name = file;
dos.writeUTF(name);
File f = new File(file);
sendFile(f, dos);
}
dos.close();
Log.d(TAG, "Client: Data written");
}
catch (IOException e) {
Log.e(TAG, e.getMessage());
}
finally {
if (socket != null) {
if (socket.isConnected()) {
try {
socket.close();
}
catch (IOException e) {
// Give up
e.printStackTrace();
}
}
}
}
void sendFile(File in, DataOutputStream out) throws IOException {
long fileLength = in.length();
out.writeLong(fileLength);
FileInputStream fis = new FileInputStream(in);
BufferedInputStream bis = new BufferedInputStream(fis);
byte buf[] = new byte[1024];
int len;
while (fileLength > 0) {
len = bis.read(buf);
if (len == -1) throw new IOException();
out.write(buf, 0, len);
fileLength -= len;
}
}
Server side:
try {
ServerSocket serverSocket = new ServerSocket(8988);
Socket client = serverSocket.accept();
BufferedInputStream bis = new BufferedInputStream(client.getInputStream());
DataInputStream dis = new DataInputStream(bis);
int filesCount = dis.readInt();
File[] files = new File[filesCount];
for(int i = 0; i < filesCount; i++)
{
Log.d(TAG, "doInBackground: " + filesCount);
//long fileLength = dis.readLong();
String fileName = dis.readUTF();
files[i] = new File(context.getExternalFilesDir("received"), Long.toString(System.currentTimeMillis()) + ".mp4" );
Log.d(TAG, "doInBackground: 1" );
File dirs = new File(context.getPackageName() + files[i].getParent());
Log.d(TAG, "doInBackground: 2" );
if (!dirs.exists()) dirs.mkdirs();
files[i].createNewFile();
Log.d(TAG, "server: copying files " + files[i].toString());
receiveFile(dis, files[i]);
}
serverSocket.close();
return "done";
}
catch (IOException e) {
Log.e(TAG, e.getMessage());
return null;
}
void receiveFile(DataInputStream in, File out) throws IOException {
long fileLength = in.readLong();
FileOutputStream fos = new FileOutputStream(out);
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte buf[] = new byte[1024];
int len;
while (fileLength > 0) {
len = (fileLength >= 1024) ? 1024 : (int) fileLength;
len = in.read(buf, 0, len);
if (len == -1) throw new IOException();
bos.write(buf, 0, len);
fileLength -= len;
}
}