I am writing a server and client file transfer module and I wanted to know If it is possible to send the file info along with file itself.Particularly I need file names and folder structure of the file on server sent to the client.
Ex. if I have c:\abc\efg\a.txt on server I want .\abc\efg\a.txt on client.
this is the code I'm using :
Server Side File Send:
Socket clientSocket=new Socket("Some IP",12345);
OutputStream out=clientSocket.getOutputStream();
FileInputStream fis=new FileInputStream(file);
int x=0;
byte[] b = new byte[4194304];
while(true){
x=fis.read(b);
if(x==-1)break;
out.write(b);
}
out.close();
Client Listener:
try {
ServerSocket ss=new ServerSocket(12345);
while(true){
final Socket client = ss.accept();
new Thread(new Runnable() {
#Override
public void run() {
try{
InputStream in = client.getInputStream();
FileOutputStream fos = new FileOutputStream("rec.txt");
int x=0;
byte[] b = new byte[4194304];
while(true){
x=in.read(b);
if(x==-1)break;
fos.write(b);
}
fos.close();
}
catch(Exception e){
}
}
}).start();
}
} catch (Exception e) {
}
You need to send the file path then the file name, use a 64 byte buffer to do that, once you get the path and name you read the file contents.
For example:
// Server
try
{
Socket clientSocket=new Socket("Some IP",12345);
OutputStream out=clientSocket.getOutputStream();
FileInputStream fis=new FileInputStream(file);
byte[] info = new byte[64];
int len = file.getPath().length();
info = file.getPath().getBytes();
for (int i=len; i < 64; i++) info[i]=0x00;
out.write(info, 0, 64);
len = file.getName().length();
info = file.getName().getBytes();
for (int i=len; i < 64; i++) info[i]=0x00;
out.write(info, 0, 64);
int x;
byte[] b = new byte[4194304];
while((x=fis.read(b)) > 0)
{
out.write(b, 0, x);
}
out.close();
fis.close();
}
catch (Exception e)
{
e.printStackTrace();
}
// Client
try
{
InputStream in = client.getInputStream();
FileOutputStream fos = new FileOutputStream("rec.txt");
byte[] path = new byte[64];
in.read(path, 0, 64);
byte[] name = new byte[64];
in.read(name, 0, 64);
int x=0;
byte[] b = new byte[4194304];
while((x = in.read(b)) > 0)
{
fos.write(b, 0, x);
}
fos.close();
}
catch(Exception e)
{
e.printStackTrace();
}
Send a header first with all information you need, then a separator (e.g. 0) then the file content. Server side reads the header till the separator then the content.
I have done this before. I used DataOutputStream at the server and DataInputStream at the client.
I used this protocol:
1. send the file name .writeUTF(fileName);
2. send the file size .writeLong(fileSize);
3. send the file .writeBytes(byteArray); // this is done inside a for loop since file size can be too big to be put into memory at once. Both the server and client size will use fileSize to determine when to stop.
The client side will use the same protocol but instead of "write", it will be "read".
Zip
1. file
2. Information about file
Send it )
Related
I am trying to transfer a file from server to client using Java and TCP, however on the client-side I am getting a socket closed exception, whereas the server has no errors when attempting to transfer the file. I am confused about this error because I did not close the socket before trying to read from it. The server accepts the connection and sends the file, but the client gets that error. Any suggestion?
The error is:
java.net.SocketException: Socket closed
Server thread's run function:
public void run() {
System.out.println("Service thread running for client at " + socket.getInetAddress() + " on port " + socket.getPort());
try {
File file = new File("hank.txt");
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
OutputStream os = socket.getOutputStream();
byte[] contents;
long fileLength = file.length();
long current = 0;
long start = System.nanoTime();
while(current!=fileLength) {
int size = 1000;
if(fileLength - current >= size) {
current += size;
}
else {
size = (int)(fileLength - current);
current = fileLength;
}
contents = new byte[size];
bis.read(contents,0,size);
os.write(contents);
System.out.println("sending file..." + (current*100)/fileLength+"% complete!");
}
os.flush();
this.socket.close();
}catch(Exception e) {
e.printStackTrace();
}
}
Client receiving the file code:
System.out.println("Going to get the file...");
socket = new Socket(response.getIP().substring(1), response.getPort());
byte[] contents = new byte[10000];
FileOutputStream fos = new FileOutputStream("hank.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
InputStream in = socket.getInputStream();
int bytesRead = 0;
System.out.println("Starting to read file...");
while((bytesRead = is.read(contents))!=-1) { //the error points to this lin
bos.write(contents,0,bytesRead);
}
bos.flush();
bos.close();
in.close();
//
socket.close();
Input stream for this socket is available in variable in
InputStream in = socket.getInputStream();
So
Change is.read(contents)) to in.read(contents))
I am working on reading a file and write same file, but the problem is the downloaded file is 2kb larger than input original file.
Some piece of code
#Override
public void run() {
try {
BufferedInputStream bis;
ArrayList<byte[]> al =new ArrayList<byte[]>();
File file = new File(Environment.getExternalStorageDirectory(), "test.mp3");
byte[] bytes = new byte[2048];
bis = new BufferedInputStream(new FileInputStream(file));
OutputStream os = socket.getOutputStream();
int read ;
int fileSize = (int) file.length();
int readlen=1024;
while (fileSize>0) {
if(fileSize<1024){
readlen=fileSize;
System.out.println("Hello.........");
}
bytes=new byte[readlen];
read = bis.read(bytes, 0, readlen);
fileSize-=read;
al.add(bytes);
}
ObjectOutputStream out1 = new ObjectOutputStream(new FileOutputStream(Environment.getExternalStorageDirectory()+"/newfile.mp3"));
for(int ii=1;ii<al.size();ii++){
out1.write(al.get(ii));
// out1.flush();
}
out1.close();
File file1 = new File(Environment.getExternalStorageDirectory(), "newfile.mp3");
Don't use an ObjectOutputStream. Just use the FileOutputStream, or a BufferedOutputStream wrapped around it.
The correct way to copy streams in Java is as follows:
byte[] buffer = new byte[8192]; // or more, or even less, anything > 0
int count;
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
out.close();
Note that you don't need a buffer the size of the input, and you don't need to read the entire input before writing any of the output.
Wish I had $1 for every time I've posted this.
I think you should use ByteArrayOutputStream not an ObjectOutputStream.
I belive this is not a raw code, but the parts of the code, placed in different procedures, otherwise it is meaningless.
For example, in case you want to stream some data from a file, process this data, and then write the data to another file.
BufferedInputStream bis = null;
ByteArrayOutputStream al = new ByteArrayOutputStream();
FileOutputStream out1 = null;
byte[] bytes;
try {
File file = new File("testfrom.mp3");
bis = new BufferedInputStream(new FileInputStream(file));
int fileSize = (int) file.length();
int readLen = 1024;
bytes = new byte[readLen];
while (fileSize > 0) {
if (fileSize < readLen) {
readLen = fileSize;
}
bis.read(bytes, 0, readLen);
al.write(bytes, 0, readLen);
fileSize -= readLen;
}
bis.close();
} catch (IOException e){
e.printStackTrace();
}
//proceed the data from al here
//...
//finish to proceed
try {
out1 = new FileOutputStream("testto.mp3");
al.writeTo(out1);
out1.close();
} catch (IOException e){
e.printStackTrace();
}
Don't forget to use try-catch directives where it needed
http://codeinventions.blogspot.ru/2014/08/creating-file-from-bytearrayoutputstrea.html
I want to receive text files through a socket connection in java, I set up the server end but before I continue with the client I would like to know if the code I made works, except I have no idea how to test this.
Any help would be much appreciated..
EDIT: I know the port is open and listening for requests, what i want is to test what happens if it receives anything, will it create a file from the input and can I test this by simulation(sending a file or bytes i dont know)?
public class Server {
private static int port = 8080;
private static int maxConnections = 100000;
// Listen for incoming connections and handle them
public static void startServer() {
int i = 0;
try {
ServerSocket listener = new ServerSocket(port);
Socket server;
System.out.println("Started server on port:" + port);
while ((i++ < maxConnections) || (maxConnections == 0)) {
RunServer connection;
server = listener.accept();
RunServer conn_c = new RunServer(server);
Thread t = new Thread(conn_c);
t.start();
System.out.println("Created new thread");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class RunServer implements Runnable {
private Socket server;
RunServer(Socket server) {
this.server = server;
}
public void run() {
int bytesRead;
int current = 0;
BufferedOutputStream bufferedOutputStream = null;
FileOutputStream fileOutputStream = null;
DataInputStream clientData = null;
File file = null;
try {
// creating connection.
System.out.println("connected.");
// receive file
byte[] byteArray = new byte[6022386];
System.out.println("Please wait downloading file");
// reading file from socket
InputStream inputStream = server.getInputStream();
file = new File("toread.txt");
clientData = new DataInputStream(inputStream);
fileOutputStream = new FileOutputStream(file);
bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
bytesRead = inputStream.read(byteArray, 0, byteArray.length);
current = bytesRead;
do {
bytesRead = inputStream.read(byteArray, current, (byteArray.length - current));
if (bytesRead >= 0)
current += bytesRead;
} while (bytesRead > -1);
bufferedOutputStream.write(byteArray, 0, current);
bufferedOutputStream.flush();
ReaderHelper.readTextFile(file);
} catch (IOException e) {
e.printStackTrace();
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (fileOutputStream != null)
fileOutputStream.close();
if (bufferedOutputStream != null)
bufferedOutputStream.close();
if (clientData != null)
clientData.close();
if (server != null)
server.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Well, your socket will be up on port 8080 right?
You can open your browser and type: http://localhost:8080. The browser will create a connection and the line
server = listener.accept();
will "unlock". If you just wanna test if the socket is listenning it will do. Reading the stream you will see the first message of the HTTP protocol.
At first you have a possible error in a reading loop
byte[] byteArray = new byte[6022386];
//some code
do {
bytesRead = inputStream.read(byteArray, current, (byteArray.length - current));
if (bytesRead >= 0)
current += bytesRead;
} while (bytesRead > -1);
If file length is more than byteArray.length which is possible, then (byteArray.length - current) would be negative.
I suggest you to use smaller array, e.g. byte[] byteArray = new byte[8192]; and read file like this
while ((bytesRead = in.read(byteArray)) > 0 ) {
current += bytesRead;
bufferedOutputStream.write(byteArray, 0, bytesRead);
}
storing it into disk chunk by chunk. And after exiting while loop current will hold total number of read bytes.
Send file from another thread, which will connect to server
Socket clientSocket = new Socket("localhost", Server.port);
BufferedReader input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
DataOutputStream output = new DataOutputStream(clientSocket.getOutputStream());
FileInputStream fileInput = new FileInputStream("fileName");
byte[] buffer = new byte[8192];
while(fileInput.read(buffer) != -1){
output.write(buffer, 0, length);
}
//close resources
I have two projects; one for my server and one for my client, I am able to send images to the server with ease. But I am wondering how would you be able to download that image you just sent to the server back to the client when I press the download button I have created on my client GUI? My code is written in java.
Many Thanks
This is my serverhandler
String fileName;
fileName = "RecievedImageoutreach1.jpg";
DataOutputStream dout = new DataOutputStream(sock.getOutputStream());
//Coding for image transfer
int flag=0,i;
String extn="";
for(i=0; i<fileName.length(); i++)
{
if(fileName.charAt(i)=='.' || flag==1)
{
flag=1;
extn += fileName.charAt(i);
}
}
if(extn.equals(".jpg") || extn.equals(".gif"))
{
try{
File file = new File(fileName);
FileInputStream fin = new FileInputStream(file);
dout.writeUTF(fileName);
byte[] readData = new byte[1024];
while((i = fin.read(readData)) != -1)
{
dout.write(readData, 0, i);
}
//ta.appendText("\nImage Has Been Sent");
dout.flush();
fin.close();
}catch(IOException ex)
{System.out.println("Image ::"+ex);}
}
}
And this is my client
public void download() throws IOException {
// Get input from the server
DataInputStream dis = new DataInputStream (sock.getInputStream());
String str,extn = "";
str = dis.readUTF();
int flag=0,i;
for(i=0;i<str.length();i++)
{
if(str.charAt(i)=='.' || flag==1)
{
flag=1;
extn+=str.charAt(i);
}
}
//**********************reading image*********************************//
if(extn.equals(".jpg") || extn.equals(".gif"))
{
File file = new File("Downloaded"+str);
FileOutputStream fout = new FileOutputStream(file);
//receive and save image from client
byte[] readData = new byte[1024];
while((i = dis.read(readData)) != -1)
{
fout.write(readData, 0, i);
if(flag==1)
{
ta.append("Image Has Been Downloaded");
flag=0;
}
}
fout.flush();
fout.close();
}
}
But when run nothing occurs? i have linked the client method to run when a button is clicked.
I would do something like this:
//Server Handler
File file = new File(fileName);
FileInputStream fin = new FileInputStream(file);
// dout.writeUTF(fileName);
byte[] readData = new byte[1024];
fin.read(readData);
fin.close();
dout.write(readData, 0, readData.length);
dout.flush();
/* while((i = fin.read(readData)) != -1)
{
dout.write(readData, 0, i);
}*/
//ta.appendText("\nImage Has Been Sent");
dout.flush();
fin.close();
}catch(IOException ex)
{System.out.println("Image ::"+ex);}
}
//Receiving image
if(extn.equals(".jpg") || extn.equals(".gif"))
{
//give path to new file
File file = new File(".//Downloaded"+str);
FileOutputStream fout = new FileOutputStream(file);
//receive and save image from client
byte[] readData = new byte[1024];
int offset =0;
while((i = dis.read(readData,0,readData.length-offset)) != -1){
offset += i;
}
fout.write(readData, 0, readData.length);
if(flag==1)
{
ta.append("Image Has Been Downloaded");
flag=0;
}
fout.flush();
fout.close();
}
}
Assuming that you would have to provide file name and then press download button. So on server side convert the image into byte stream and write over the connection socket. On client side recieve bytes into buffer and then create FileOutputStream providing the directory for output. Write the recieved bytes onto the file using the outputstream created.
This question already has answers here:
Java multiple file transfer over socket
(3 answers)
Closed 7 years ago.
I'm making a communicator with ability to send files.
So far I managed to make text sending working using additional thread (listener).
I'm trying to make the same thing with files, but I don't know, how can I make a file listener - a thread, that detects incoming file, downloads it and listens for another file. Also, I don't know if I'm making my file sender properly. Could you help?
Current sender code:
try {
InputStream in = new FileInputStream(fileToSend);
OutputStream out = fileConn.getOutputStream();
Controller.copyData(in, out);
out.close();
in.close();
} catch (IOException e) {
System.out.println("Problem!");
}
And receiver code:
while (true)
{
try {
InputStream in = socket.getInputStream();
OutputStream out = new FileOutputStream("hi.txt"); //temporary
Controller.copyData(in, out);
out.close();
in.close();
} catch (IOException e) {
System.out.println("Problem!");
}
}
EDIT: I forgot to add my copyData. There it is:
public static void copyData(InputStream in, OutputStream out) throws IOException{
byte[] buf = new byte[8192];
int len = 0;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
}
You can achive tha by just adding to your listening thread option to wait for diffrent messages/options and react accordingly. For example:
private class WaitingThread extends Thread {
volatile boolean awaitsServer = false;
DataInputStream dataInput = new DataInputStream(inputStream);
public void run() {
while (connected) {
int message = 0;
if (awaitsServer == true) {
if (dIn.available() ==0) {
view.setLog("waiting");
} else {
message = dIn.readInt();
switch (tempMessage) {
// TO DO ALL KIND OF COMMUNICATION
case 1:
int filesize = dataInput.readInt();
int bytesRead;
int currentTot = 0;
byte[] bytearray = new byte[filesize];
int len = dataInput.readInt();
FileOutputStream fos = new FileOutputStream(currentlySelectedFile);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = dataInput.read(bytearray, 0, bytearray.length);
currentTot = bytesRead;
do {
bytesRead = dataInput.read(bytearray, currentTot,
(len - currentTot));
if (bytesRead >= 0)
currentTot += bytesRead;
} while (currentTot < len);
bos.write(bytearray, 0, currentTot);
bos.close();
}
case 2: //GET TEXT
case 3: //DO SOMETHING ELSE
}}}
Btw you have example how to send files.