i have a server which sending thousands of tiny files like below:
static File file = null;
static File temp = null;
private static ServerSocket serverSocket;
private static Socket socket;
public static void main(String[] args) throws FileNotFoundException, IOException
{
serverSocket = new ServerSocket(3000);
socket = serverSocket.accept();
System.out.println("Connected");
File folder = new File("C:...\\Desktop\\thousands_of_tiny_files");
File[] listOfFiles = folder.listFiles();
File result[]=new File[listOfFiles.length];
byte [] bytearray = null;
FileInputStream fin =null;
BufferedInputStream bin = null;
for(int j=0;j<listOfFiles.length;j++){
String path= listOfFiles[j].getPath();
result=sendFile(path);
for(int i=0;i<result.length;i++)
{
fin = new FileInputStream(result[i]);
bin = new BufferedInputStream(fin);
bytearray = new byte [(int)result.length];
bin.read(bytearray,0,bytearray.length);
OutputStream os = socket.getOutputStream();
System.out.println("Sending Files "+ result[i]);
os.write(bytearray,0,bytearray.length);
os.flush();
System.out.println("File transfer completed");
}
}
fin.close();
bin.close();
socket.close();
}
public static File[] sendFile(String path)
{
File folder = new File(path);
File[] listOfFiles = folder.listFiles();
File[] resultt = new File[listOfFiles.length];
for(int i=0;i<listOfFiles.length;i++)
{
temp=listOfFiles[i];
if(temp.isFile() && temp!=null)
resultt[i]=temp;
}
return resultt;
}
it is successfull but my problem is in client side. i dont know how to distinguish between the files and write them seperately into the client.
EDIT2:
I changed the server side code like following using ZipOutputStream but still dont know how to unzip and write it in the client (mostly, dont know how to define the FileOutputStream in client:
for(int i=0;i<result.length;i++)
{
fin = new FileInputStream(result[i]);
bytearray = new byte [(int)result.length];
ZipOutputStream zipOpStream = new ZipOutputStream(socket.getOutputStream());
zipOpStream.putNextEntry(new ZipEntry(result[i].getName()));
System.out.println("Sending Files "+ result[i]);
zipOpStream.write(bytearray,0,bytearray.length);
zipOpStream.flush();
System.out.println("File transfer completed");
}
}
socket.close();
}
and the reciever code:
socket = new Socket("127.0.0.1",3000);
String outDir = "C:...\\Desktop\\here";
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
ZipInputStream zips = new ZipInputStream(bis);
ZipEntry zipEntry = null;
while(null != (zipEntry = zips.getNextEntry())){
String fileName = zipEntry.getName();
File outFile = new File(outDir + "/" + fileName);
System.out.println("----["+outFile.getName()+"], filesize["+zipEntry.getCompressedSize()+"]");
if(zipEntry.isDirectory()){
File zipEntryFolder = new File(zipEntry.getName());
if(zipEntryFolder.exists() == false){
outFile.mkdirs();
}
continue;
}else{
File parentFolder = outFile.getParentFile();
if(parentFolder.exists() == false){
parentFolder.mkdirs();
}
}
System.out.println("ZipEntry::"+zipEntry.getCompressedSize());
FileOutputStream fos = new FileOutputStream(outFile);
int fileLength = (int)zipEntry.getSize();
byte[] fileByte = new byte[fileLength];
zips.read(fileByte);
fos.write(fileByte);
fos.close();
socket.close();
}
now i get an exceptiom"negative NegativeArraySizeException"
Exception in thread "main" java.lang.NegativeArraySizeException
at recieve.Reciever.<init>(Reciever.java:71)
at recieve.Recieve$1.<init>(Recieve.java:28)
at recieve.Recieve.main(Recieve.java:28)
ZipEntry::-1
which probably is because of
int fileLength = (int)zipEntry.getSize();
but how can I solve this? i need the siz of next entry of zip folder for writing into the file.
but the size is in Long not int
How about writing it into a ZipOutputStream where you can receive the file on the other side as a single stream. Once you have the entire output, you can write the reverse code to deflate the zip file and get all the files. Providing a sample code for writing the Zip into your socket stream, you can build your code over this.
Refer this length for a sample Server and Client implementation sending the file using a ZipOutputStream Stick2Code
Related
I have attempted to write a program that simply sends files from the client to server. The program has a gui where you enter the file path and what you want the new filename to be on the server. The program works fine for the first send but freezes on the second send and the second file does not get written to server. Any help would be appreciated im really stuck thank you guys so much in advance.
Client Code
ServerSocket serverSocket;
public void sendFile(String filePath, String fileFieldName)throws IOException{
//Parameters filePath is a full direct path of file to be sent
//Example of filePath "C:\Users\Someone\Desktop\Capture3333333.PNG"
//FileFieldName is the desired name and extension of file being sent
// i removed my server ip and just put in a string for demonstration
Socket socket = new Socket("IP GOES HERE", 5557);
System.out.println("Is sending?");
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
DataOutputStream dos = new DataOutputStream(bos);
File files = new File(filePath);
long length = files.length();
dos.writeLong(length);
dos.writeUTF("\\"+ fileFieldName);
FileInputStream fis = new FileInputStream(filePath);
BufferedInputStream bis = new BufferedInputStream(fis);
int theByte = 0;
while((theByte = bis.read()) != -1) bos.write(theByte);
bis.close();
bos.flush();
dos.close();
}
Server Code
ServerSocket serverSocket;
public void fileListenThread () throws IOException {
while(true){//This is so the socket keeps listening
serverSocket = new ServerSocket(5557);
Socket socket = serverSocket.accept();
if(socket.isConnected()){
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
DataInputStream dis = new DataInputStream(bis);
File files ;
long fileLength = dis.readLong();//This reads file length from client
String fileName = dis.readUTF();//This reads filename from client
files = new File( System.getProperty("user.home") + "\\Desktop\\Top-Brand\\Images\\" + fileName );//File received from client is written to this path
FileOutputStream fos = new FileOutputStream(files);
BufferedOutputStream bos = new BufferedOutputStream(fos);
for(int j = 0; j < fileLength; j++)
bos.write(bis.read());
bos.flush();
bos.close();
dis.close();
}
}
}
Move the line
serverSocket = new ServerSocket(5557);
out of the while loop. It should be before the loop, not inside it. If you put it in the loop, then after each file transfer, you will be creating another server socket which will then fail to bind because the old one is still there.
RESOLVED - My server socket was inside the loop causing a net bind exception, here is working code for server, client works just fine
ServerSocket serverSocket;
public void fileListenThread () throws IOException {
serverSocket = new ServerSocket(5557);
while(true){//This is so the socket keeps listening
Socket socket = serverSocket.accept();
if(socket.isConnected()){
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
DataInputStream dis = new DataInputStream(bis);
File files ;
long fileLength = dis.readLong();//This reads file length from client
String fileName = dis.readUTF();//This reads filename from client
files = new File( System.getProperty("user.home") + "\\Desktop\\Top-Brand\\Images\\" + fileName );//File received from client is written to this path
FileOutputStream fos = new FileOutputStream(files);
BufferedOutputStream bos = new BufferedOutputStream(fos);
for(int j = 0; j < fileLength; j++)
bos.write(bis.read());
bos.flush();
bos.close();
dis.close();
}
}
}
I have a file in the server, I want to create three java APIs, which will do the below three operations in dependently.
Get the file size
Move a file with different file name to a different server location
Zip the file
In my existing code we are executing Linux commands to perform those operations, unfortunately, Linux commands are not getting executed, this is due to some server/set up issue, so I am forced to use Java commands.(We use JDK 1.6)
I am not a Java developer. I have gone through some of the previously answered questions, but they are not explaining about file in server path. Any help is much appreciated.
To get the file size in bytes:
File file = new File("filename.txt");
long fileSize = file.length();
To move a file you must first copy it and then delete the original:
InputStream inStream = null;
OutputStream outStream = null;
try {
File fromFile = new File("startfolder\\filename.txt");
File toFile = new File("endfolder\\filename.txt");
inStream = new FileInputStream(fromFile);
outStream = new FileOutputStream(toFile);
byte[] buffer = new byte[1024];
int length;
while ((length = inStream.read(buffer)) > 0){
outStream.write(buffer, 0, length);
}
inStream.close();
outStream.close();
fromFile.delete();
} catch(IOException e) {
e.printStackTrace();
}
To zip a file:
byte[] buffer = new byte[1024];
try {
FileInputStream fileToZip = new FileInputStream("filename.txt");
FileOutputStream fileOutputStream = new FileOutputStream("filename.zip");
ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream);
ZipEntry zipEntry= new ZipEntry("filename.txt");
zipOutputStream.putNextEntry(zipEntry);
int len;
while ((len = fileToZip.read(buffer)) > 0) {
zipOutputStream.write(buffer, 0, len);
}
fileToZip.close();
zipOutputStream.closeEntry();
zipOutputStream.close();
} catch(IOException e) {
e.printStackTrace();
}
I have a simple Fileserver and Client (code from the web) that let me send files to my other laptop inside my home LAN. Now, the file sent from the server to the client is hardcoded but i want to prompt user at client-side to input a filename, send it to the server and send back the specified file. My code looks like this:
Server
import java.net.*;
import java.io.*;
public class Server {
public static void main(String[] args) {
BufferedOutputStream outputStream;
BufferedInputStream inputStream;
FileInputStream fileInput;
String file = "C:/java/file.mp4";
try {
ServerSocket socket = new ServerSocket(12345);
while(true) {
Socket clientSocket = socket.accept();
outputStream = new BufferedOutputStream(clientSocket.getOutputStream());
fileInput = new FileInputStream(file);
inputStream = new BufferedInputStream(fileInput);
int packetToSend = -1;
byte[] buffer = new byte[8192];
while((packetToSend = inputStream.read(buffer)) > -1) {
outputStream.write(buffer, 0, packetToSend);
System.out.println("sending " + packetToSend + " bytes");
outputStream.flush();
}
}
}
catch(Exception e) {
e.printStackTrace();
}
}
}
And thats the Client Code (IPAdress of the Server is argument s[0] and the path to save the file is s[1] in main method.
import java.net.*;
import java.io.*;
public class Client {
public static void main(String[] s) {
try {
String address = new String(s[0]);
String fileToSave = new String(s[1]);
Socket socket = new Socket(address,12345);
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
FileOutputStream fos = new FileOutputStream(fileToSave);
int n;
byte[] buffer = new byte[8192];
System.out.println("Connected");
while ((n = bis.read(buffer)) > 0) {
System.out.println("received "+n+" bytes");
fos.write(buffer, 0, n);
fos.flush();
}
System.out.println("recieved");
}
catch(Exception e) {
e.printStackTrace();
}
}
}
I want to promt the user on client side to input a filename after client is connected to send to the server and the server should send that file.
i tried to put this in client side after System.out.println("connected");
System.out.print("Insert filename to download: ");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String input = null;
try {
input = reader.readLine();
} catch (IOException ioe) {
System.out.println("Eingabe konnte nicht verarbeitet werden!");
System.exit(1);
}
System.out.println("Eingabe: " + input);
and on server side i put this after outputStream = new BufferedOutputStream(clientSocket.getOutputStream()); to override the hardcoded filename at the beginning of server class.
inputStream = new BufferedInputStream(clientSocket.getInputStream());
fileInputStream = new FileInputStream(inputStream);
fileInputStream = new BufferedInputStream(fileInput);
Once a connection is established, client side is idle (cant input something) and server side does nothing after writing out to console "new connection".
how can i solve this please?
The client sends to the server the filename. So first you must extract the filename from the socket's input stream. To do that you need to establish a protocol for how information will be sent. This is critical when dealing with TCP streams, which is different from UDP datagrams. Typically two newlines is used to convey the end of a message. But because it is not normal for a filename to have a newline in it, we will use one newline to convey end of message.
We can then use Scanner to extract the filename from the client's socket.
String fileName;
Scanner scanner = new Scanner (clientSocket.getInputStream());
while(scanner.hasNextLine())
{
fileName = scanner.nextLine();
break;
}
fileInputStream = new FileInputStream(fileName);
fileInputStream = new BufferedInputStream(fileInput);
In this example the fileName must be the absolute path to that file as its sits in the server's file system. In future versions you might want to use a directory on the server where files are stored and the client can give you the relative path to file from that directory. Here is how that would look like.
String fileName;
Scanner scanner = new Scanner (clientSocket.getInputStream());
while(scanner.hasNextLine())
{
fileName = scanner.nextLine();
break;
}
fileInputStream = new FileInputStream(FILE_DIR + fileName);
fileInputStream = new BufferedInputStream(fileInput);
The variable FILE_DIR would look something like:
static String FILE_DIR = "C:/java/";
And the file that the client would send over would just be file.mp4
EDIT 1:
Here is the Client code with the recommendations. Please note that this test quality code, not production code.
import java.net.*;
import java.io.*;
public class Client {
static String FILE_DIR = "./";
public static void main(String[] s) throws IOException {
/**
* Establish socket using main args.
*/
String address = s[0];
while (true) {
/**
* Get the file name from the user.
*/
System.out.print("Insert filename to download: ");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String fileName = null;
try {
fileName = reader.readLine();
} catch (IOException ioe) {
System.out.println("Eingabe konnte nicht verarbeitet werden!");
System.exit(1);
}
System.out.println("Eingabe: " + fileName);
/**
* Create the socket.
*/
Socket socket = new Socket(address, 12345);
/**
* With file name in hand, proceed to send the filename to the
* server.
*/
//...put in try-with-resources to close the outputstream.
try (BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream())) {
System.out.println("Connected: Sending file name to server.");
//...send file name plus a newline.
bos.write((fileName + '\n').getBytes());
bos.flush();
/**
* Get the file contents and save to disk.
*/
//...wrap input stream in DataInpuStream for portability.
//...put in try-with-resource to close the input stream.
try (BufferedInputStream bis = new BufferedInputStream(new DataInputStream(socket.getInputStream()))) {
DataOutputStream fos = new DataOutputStream(new FileOutputStream(fileName));
int n;
byte[] buffer = new byte[8192];
System.out.println("Connected: Recieving file contents from server.");
while ((n = bis.read(buffer)) > 0) {
System.out.println("received " + n + " bytes");
fos.write(buffer, 0, n);
fos.flush();
}
System.out.println("recieved");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
and here's the server code. Please note the server is retrieving the file from local directory called ./files/, please change that to whatever directory you want.
import java.net.;
import java.io.;
import java.util.Scanner;
public class Server {
static String FILE_DIR = "./files/";
public static void main(String[] args) {
BufferedInputStream inputStream;
FileInputStream fileInput;
try {
ServerSocket socket = new ServerSocket(12345);
while (true) {
Socket clientSocket = socket.accept();
/**
* Get the file name from the client. File name is one per line.
*/
//...put in trye-with-resources to close InputStream for us.
try (InputStream inputFromClient = clientSocket.getInputStream()) {
System.out.println("Connected: Getting file name from client.");
Scanner scanner = new Scanner(inputFromClient);
String fileName;
if (scanner.hasNextLine()) {
fileName = scanner.nextLine();
System.out.println("File name = " + fileName);
} else {
//...no line found, continue. consider logging an error or warning.
continue;
}
/**
* With fileName in hand, we can proceed to send the
* contents of the file to the client.
*/
fileInput = new FileInputStream(fileName);
//...use DataInputStream for more portable code
DataInputStream dataInput = new DataInputStream(fileInput);
inputStream = new BufferedInputStream(dataInput);
int packetToSend = -1;
byte[] buffer = new byte[8192];
//...consider closing the OutputStream to let the client know.
//...use try-with-resource to close the outputStream for us.
//...wrap your outputStream in DataOutputStream
try (BufferedOutputStream outputStream = new BufferedOutputStream(new DataOutputStream(clientSocket.getOutputStream()))) {
while ((packetToSend = inputStream.read(buffer)) > -1) {
outputStream.write(buffer, 0, packetToSend);
System.out.println("sending " + packetToSend + " bytes");
outputStream.flush();
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
I am writing a client/server program where I send a file over sockets. I create a file object in the server code, but I do not know what to call the file as the file the client sends is user-defined.
NOTE: I want to be able to receive larger files e.g. .mp3 files etc.
server code:
try{
ServerSocket servsock = new ServerSocket(123456);
File myFile = new File(/* I dont know how to get the file name here*/);
while (true) {
Socket sock = servsock.accept();
System.out.println("Connection accepted, ip - port - ");
byte[] mybytearray = new byte[(int) myFile.length()];
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile));
bis.read(mybytearray, 0, mybytearray.length);
OutputStream os = sock.getOutputStream();
os.write(mybytearray, 0, mybytearray.length);
os.flush();
sock.close();
bis.close();
servsock.close();
}
} catch(IOException e) {
System.out.println("Error");
}
Create a pojo to hold file name and bytes
public class FileObject {
private String fileName;
private byte[] fileData;
//getter/setters
}
Set the file name and data on clientSide
ClientCode
FileObject fileObject = new FileObject();
//set the fileName here
fileObject.setFileName(fileName);
File file = new File(filePath);
if (file.isFile()) {
//set data here
fileObject.setFileData(fileBytes);
}
//Now writing the FileObject object to socket
outputStream.writeObject(fileObject);
ServerCode
//Cast the received input stream to get data and file name
fileObject = (FileObject ) inputStream.readObject();
I want to make my server to be able to get the name of the file that will be sent to it and then after getting that file it could save it in new location with right name.
Here is the server code:
class TheServer {
public void setUp() throws IOException { // this method is called from Main class.
ServerSocket serverSocket = new ServerSocket(1991);
System.out.println("Server setup and listening...");
Socket connection = serverSocket.accept();
System.out.println("Client connect");
System.out.println("Socket is closed = " + serverSocket.isClosed());
BufferedReader rd = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String str = rd.readLine();
System.out.println("Recieved: " + str);
rd.close();
InputStream is = connection.getInputStream();
int bufferSize = connection.getReceiveBufferSize();
FileOutputStream fos = new FileOutputStream("C:/" + str);
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte[] bytes = new byte[bufferSize];
int count;
while ((count = is.read(bytes)) > 0) {
bos.write(bytes, 0, count);
}
bos.flush();
bos.close();
is.close();
connection.close();
serverSocket.close();
}
}
and here is the client code:
public class TheClient {
public void send(File file) throws UnknownHostException, IOException { // this method is called from Main class.
Socket socket = null;
String host = "127.0.0.1";
socket = new Socket(host, 1991);
// Get the size of the file
long length = file.length();
if (length > Integer.MAX_VALUE) {
System.out.println("File is too large.");
}
BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
wr.write(file.getName());
wr.flush();
byte[] bytes = new byte[(int) length];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
int count;
while ((count = bis.read(bytes)) > 0) {
out.write(bytes, 0, count);
}
out.flush();
out.close();
fis.close();
bis.close();
socket.close();
}
}
I made few test of my own and it seems that my client is sending the name of the file right, but somehow server gets it wrong. For example if my client tells that name of the file is "test.txt" my server gets it for example like "test.txt´--------------------" or "test.txtPK". I can't understand why it does't get the name normally. Anyone knows why this happens? Or is there an easier way to do this? And my second question is, how can I use this not only in localhost but everywhere? I tried changing my host to my IP adress but it didnt work. Thanks.
You never send end of line after the filename. Therefore, when server reads using readLine() it will read all characters until it find first end of line which may be somewhere in file content. Sometimes it's after '-----' and sometimes after 'PK'.