I have a Java client/server desktop application, where the communication between client and server is based on Sockets, and the messages exchanged between client and server are serialized objects (message objects, that incapsulate requests and responses).
Now I need to make the client able to upload a file from the local computer to the server, but I can't send the File through the buffer, since the Buffer is already used for exchanging the message objects.
Should i open another stream to send the file, or is there any better way to upload a file for my situation?
I need to make the client able to upload a file from the local computer to the server
- Open a Solely Dedicated Connection to the Server for File uploading.
- Use File Transfer Protocol to ease your work, and moreover its quite easy and reliable to use the Apache's common lib for File uploading and downloading....
See this link:
http://commons.apache.org/net/
You really only have two options:
Open another connection dedicated to the file upload and send it through that.
Make a message object representing bits of a file being uploaded, and send the file in chunks via these message objects.
The former seems simpler & cleaner to me, requiring less overhead and less complicated code.
You can keep your solution and pass the file content as an object, for example as a String - use Base64 encoding (or similar) of the content if it contains troublesome characters
Related
Hi and thanks in advance,
So I have a program which already creates a socket and can send strings both ways between the server and client using UDP.
However, I need to ask something before I continue with trying to send a file (specifically a text file) over my connection.
Is there a way to physically send an actual file over the connection as apposed to simply sending the files contents, or does sending it contents count as sending the files itself?
I just want to make sure on this before I continue with my program.
Thank you.
A file is not a physical object. It is more an idea of interpreting your disks magnetical (or electrical) state.
A "file" is mainly its content. There is some additional information like permissions, owner, last edit date and so on. But I assume that you don't want to send these information.
I have no idea what the specific goal is you are trying to achieve but it is safe to say, that for most applications it is perfectly fine to think of the contents of a file when saying "file".
In my webapp users can download the files among themselves. If a user A has shared a file F , then user B after connecting to A can download the file F from A. Till now each user makes a simple HTTP connection like :xxx.xxx.xxx.xxx/FileList with another user. The file resides on the local hard disk of each user. So that a user can download a file there were two options in my mind.
As the user shares a file,copy that file into the web-app directory of the server,so that the download link becomes as simple as Click to download.
Run a separate FTP server on each node.
I don't know which one of these is a better option but the first one seems very simple to me. What are the ways each client can share the files,without having to copy the stuff somewhere in the webapp directory. How in this case I can use a P2P protocol ?
NOTE : I am using Tomcat 7.
Real P2P is impossible without opening a listening socket on the client machine (that imposes you have to install something on client machine).
If you don't want to STORE the files on the server, I would rather recommend a "connection server", which serves as a gateway between the two users. User A will upload, user B will download at the same time, all you need is to make the bytebuffer in memory. The downloaded bytes can be dropped.
You can write a small client-side program in any language for updating the available files, and receiving the upload request from the server side (also execute the upload)
I would recommend using TCP sockets for upload to the server side, this way you have direct control over the uploaded bytes (streams).
There are some interesting technical issues here (blocking streams, metadata (filename, length, createdate, ...), data consistency, error handling, etc.) that should be taken into consideration. Nice task.
I don't recommend FTP because you cannot control the authentication and authorisation (who can see the files).
I am playing around with Android Sockets and I currently I am trying to send a file via WiFi. I have a simple protocol that uses few notification classes. Everything works OK on Java client and Java server, but I want to do the same thing with C# (or C++) server/client and Java client/server. I need to decide how to serialize my notification data.
I was thinking about XML format. It would contain a notification ID, client ID and some data (i.ex. chunk of a file).
How can I save a chunk of a file (or any byte array) into a XML file (or text based file)?
Maybe I am thinking completely wrong way?
Run your data through a Base64 encoder and then stick that data into a CDATA section in your xml file. Apache makes a Base64 library for Java. I'm sure it wouldn't be too hard to find one for C#/C++.
Users of my web application have an option to start a process that generates a CSV file (populated by some data from a database) and uploads it to an FTP server (and another department will read the file from there). I'm just trying to figure out how to best implement this. I use commons net ftp functionality. It offers two ways to upload data to the FTP server:
storeFile(String remote, InputStream local)
storeFileStream(String remote)
It can take a while to generate all the CSV data so I think keeping a connection open the whole time (storeFileStream) would not be the best way. That's why I want to generate a temporary file, populate it and only then transfer it.
What is the best way to generate a temporary file in a webapp? Is it safe and recommended to use File.createTempFile?
As long as you don't create thousands of CSV files concurrently the upload-time doesn't matter from my point of view. Databases usually output the data row by row and if this is already the format you need for the CSV file I strongly recommend not to use temporary files at all - just do the conversion on-the-fly:
Create an InputStream implementation that reads the database data row by row, converts it to CSV and publish the data via it's read() methods.
BTW: You mentioned that the conversion is done by a web application and that it can take a long time - this can be problematic as the default web client has a timeout. Therefore the long lasting process should be better done by a background thread only triggered by the webapp interface.
It is ok to use createTempFile, new File(tmpDir, UUID.randomUUID().toString()) can do as well. Just do not use deleteOnExit(), it is a leak master. Make sure you delete the file on your right own.
Edit: since you WILL have the data in memory, do not store it anywhere; wrap a java.io.ByteArrayInputSteam and use the method w/ the InputStream. Much neater and better solution.
I need a simple application, preferably a cross-platform one, that enables sending of files between two computers.
It just need to accept and send the files, and show a progress bar. What applications could I use or how could I write one?
Sending and Receiving Files
The sending and receiving of a file basically breaks down to two simple pieces of code.
Recieving code:
ServerSocket serverSoc = new ServerSocket(LISTENING_PORT);
Socket connection = serverSoc.accept();
// code to read from connection.getInputStream();
Sending code:
File fileToSend;
InputStream fileStream = new BufferedInputStream(fileToSend);
Socket connection = new Socket(CONNECTION_ADDRESS, LISTENING_PORT);
OutputStream out = connection.getOutputStream();
// my method to move data from the file inputstream to the output stream of the socket
copyStream(fileStream, out);
The sending piece of code will be ran on the computer that is sending the code when they want to send a file.
The receiving code needs to be put inside a loop, so that everytime someone wants to connect to the server, the server can handle the request and then go back to waiting on serverSoc.accept().
To allow sending files between both computers, each computer will need to run the server (receiving code) to listen for incoming files, and they will both need to run the sending code when they want to send a file.
Progress Bar
The JProgressBar in Swing is easy enough to use. However, getting it to work properly and show current progress of the file transfer is slightly more difficult.
To get a progress bar to show up on a form only involves dropping it onto a JFrame and perhaps setting setIndeterminate(false) so hat it shows that your program is working.
To implement a progress bar correctly you will need to create your own implementation of a SwingWorker. The Java tutorials have a good example of this in theirlesson in concurrency.
This is a fairly difficult issue on its's own though. I would recommend asking this in it's own question if you need more help with it.
Woof is a cool Python script that might work for you:
http://www.home.unix-ag.org/simon/woof.html
I would strongly consider using FTP. Apache has a FTP client and a server
Edit: spdenne's suggestion of HTTP is also good, especially if everyone has Java 6. If not, you can use something like Tiny Java Web Server.
You can write one by using Socket programming in Java. You would need to write a Server and a Client program. The server would use a ServerSocket to listen for connections, and the Client would use a Socket to connect to that server on the specified port.
Here's a tutorial: http://www.javaworld.com/jw-12-1996/jw-12-sockets.html
Sun's Java 6 includes a light-weight HTTP server API and implementation. You could fairly easily use this to serve your file, using URLConnection to obtain it.
Check out this tutorial, it's a really basic example. You would probably also want to send control headers prior to the actual file being sent, containing the size of the file, filename, etc.
Alternatively, base it on an existing protocol, like this project.
Can you install FTP servers on (one of) your machines ?
If you can, you will just have to use a FTP client (FileZilla for example, which have a progress bar).
Two popular apps are "scp" and "rsync". These are standard on Linux, are generally available on Unix and can be run on Windows under cygwin, although you may be able to find windows-native apps that can do it as well. (PuTTY can serve as an SCP client).
For any sort of pc-to-pc file transfer, you need to have a listener on the destination PC. This can be a daemon app (or Windows system process), or it can be a Unix-style "superserver" that's configured to load and run the actual file-copy app when someone contacts the listening port.
SCP and one of the rsync modes do require that there be some sort of remote login capability. Rsync can also publish resources that it will handle directory. Since the concept of a Windows "remote login" isn't as well-established as it is under Linux, this may be preferable. Plus it limits remote access to defined sources/targets on the destination machine instead of allowing access to any (authorized) part of the filesystem.
To transfer over a network more efficiently. Take a look at this article that explains efficient data transfer through zero copy