i am creating a desktop client server application, in which i am capturing the frames, in jpg images, rendered by the renderer and storing them on the client side.
now i need to upload the images to the server.
i tried this by
placing a separate thread for every captured image to upload it directly to the server but it was very time consuming. Also i tried to upload all the images from the client after the capturing is stopped, but that is not the case i want.
SO is there a way to upload the directly captured images to server effectievely.
for capturing images i am using BufferedImage and ImageIO.write methods
Thanks in advance
Image uploading Over socket is the fastest way to upload image on server because data will be passed to server as byte stream.
Below is simple Socket Client and Socket Sever to achieve Image upload
Client
public class ImageUploadSocketClient {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("localhost",6666);
OutputStream outputStream = socket.getOutputStream();
BufferedImage image = ImageIO.read(new File("path to image /your_image.jpg"));
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", byteArrayOutputStream);
byte[] size = ByteBuffer.allocate(4).putInt(byteArrayOutputStream.size()).array();
outputStream.write(size);
outputStream.write(byteArrayOutputStream.toByteArray());
outputStream.flush();
socket.close();
}
}
Server
public class ImageUploadSocketRunnable implements Runnable{
public static final String dir="path to store image";
Socket soc=null;
ImageUploadSocketRunnable(Socket soc){
this.soc=soc;
}
#Override
public void run() {
InputStream inputStream = null;
try {
inputStream = this.soc.getInputStream();
System.out.println("Reading: " + System.currentTimeMillis());
byte[] sizeAr = new byte[4];
inputStream.read(sizeAr);
int size = ByteBuffer.wrap(sizeAr).asIntBuffer().get();
byte[] imageAr = new byte[size];
inputStream.read(imageAr);
BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageAr));
System.out.println("Received " + image.getHeight() + "x" + image.getWidth() + ": " + System.currentTimeMillis());
ImageIO.write(image, "jpg", new File(dir+System.currentTimeMillis()+".jpg"));
inputStream.close();
} catch (IOException ex) {
Logger.getLogger(ImageUploadSocketRunnable.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(13085);
while(true){
Socket socket = serverSocket.accept();
ImageUploadSocketRunnable imgUploadServer=new ImageUploadSocketRunnable(socket);
Thread thread=new Thread(imgUploadServer);
thread.start();
}
}
}
On server You should create different thread for different client socket in this way you can achieve concurrent image upload from different clients.
Hope above example will help you.
Related
I'm writing a trading program that allows users to upload their own images for other clients to view when looking at their posted listing. The image file (.png or .jpeg file) is sent from the server when requested.
It seems that when using a FileInputStream as the parameter for a new Image, the client attempting to open the image is looking for that file on their own computer (checking it's own file system) instead of directly reading the image file itself that has been sent to it from the server.
In the example I am posting, let's assume that this is ran in the IDE and not as a JAR. The server program who is sending the file is able to access "avatar.png" successfully from its 'src' directory.
I have built a minimal executable example below, consisting of a server and client to represent the realistic issue at hand. The server and client examples were ran on separate computers on a local network. The example replicates the issue.
From the FileInputStream documentation:
FileInputStream is meant for reading streams of raw bytes such as image data.
The example throws the following exception:
java.io.FileNotFoundException: avatar.png (No such file or directory)
Which shows that the client is looking for 'avatar.png' on it's own file system.
For example, the server:
public class ImageTesterServer {
public static void main(String[] args) {
ImageTesterServer server = new ImageTesterServer();
server.sendImage();
}
private void sendImage()
{
ServerSocket server = null;
Socket client = null;
try {
// Accept client connection, create new File from the 'avatar.png' image, and send to client
server = new ServerSocket();
System.out.println("Awaiting client connection...");
client = server.accept();
System.out.println("Client connected.");
File imageFile = new File("avatar.png");
ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
oos.writeObject(imageFile);
System.out.println("Sent image file.");
} catch (IOException e) {
e.printStackTrace();
}
finally { // Close sockets
try {
if (client != null)
client.close();
if (server != null)
server.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
The client:
public class ImageTesterClient extends Application {
public static void main(String[] args)
{
Application.launch(args);
}
#Override
public void start(Stage primaryStage)
{
ImageTesterClient client = new ImageTesterClient();
Image avatar = client.getServerFile(); // Retrieve the image's file from the server
ImageView picture = new ImageView(avatar);
StackPane root = new StackPane();
root.getChildren().add(picture);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
private Image getServerFile()
{
Socket socket = null;
ObjectInputStream ois;
try {
socket = new Socket("192.168.1.147", 5000); // Open new socket connection to server on another local network computer
ois = new ObjectInputStream(socket.getInputStream());
File imageFile = (File)ois.readObject();
Image avatar = new Image(new FileInputStream(imageFile));
return avatar;
} catch (IOException | ClassNotFoundException ex) {
ex.printStackTrace();
}
finally { // Close the socket if not null
try {
if (socket != null)
socket.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
return null;
}
}
How do I force the client Image to use the File (avatar.png) itself that has been received from the server, instead of it attempting to look on it's own file system?
The File class does not represent a file’s contents. It is merely a representation of a file path. This confusion is one of many reasons the File class is considered obsolete (though not deprecated), and has been replaced by the Path class.
So, when you do oos.writeObject(imageFile);, you are not sending the contents of the file, only the path of that file. Obviously, the existence of a file path on one computer does not guarantee that the same path is valid on another computer.
You will have to send the file’s content separately. One way to do this is to open a FileInputStream, wrap it in a BufferedInputStream, and use that BufferInputStream’s transferTo method:
oos.writeObject(imageFile);
try (InputStream stream =
new BufferedInputStream(new FileInputStream(imageFile))) {
stream.transferTo(oos);
}
And on the client side, use the File’s length to determine how many bytes to read:
File imageFile = (File) ois.readObject();
long length = imageFile.length();
Path imagePath = Files.createTempFile(null, imageFile.getName());
try (FileChannel imageChannel = FileChannel.open(imagePath,
StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) {
imageChannel.transferFrom(Channels.newChannel(ois), 0, length);
}
Image avatar = new Image(imagePath.toUri().toString());
I am sending a screenshot from java server hosted on a machine. The screenshot would be send to an android device through sockets in form of a byte stream array. But the array which I am getting in the android device is not getting converted to bitmap. Below I am attaching the java server code, android code and the logcat.
Here is the java server code for sending the screenshot captured.
socket2 = serverSocket2.accept();
System.out.println("A client has connected");
Robot robot = new Robot();
String format = "jpg";
String fileName = "FullScreenshot." + format;
Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage screenFullImage = robot.createScreenCapture(screenRect); // captured image
ImageIO.write(screenFullImage, format, new File("C:\\Users\\User\\Desktop\\"+fileName));
ByteArrayOutputStream bao=new ByteArrayOutputStream();
ImageIO.write(screenFullImage,format,bao);//ye
byte[] ar=bao.toByteArray();
System.out.println("Parental block is executed");
mainWriter = new BufferedWriter(new OutputStreamWriter(socket2.getOutputStream()));
mainWriter.write(java.util.Arrays.toString(ar));
mainWriter.newLine();
mainWriter.flush();
System.out.println("A full screenshot saved!");
serverSocket2.close();
socket2.close();
mainWriter.close();
Testing t = new Testing();
Here is the android code where I am getting the byte stream array.
public void PCConnection(final View view) // just for this activity
{
new Thread()
{
public Socket socket;
public void run()
{
try
{
Log.i(DebuggString,"Attempting to connect to the server");
socket = new Socket(hostname,60120);
Log.i(DebuggString,"Connection established");
mivScreenShot = (ImageView) findViewById(R.id.ivScreenShot);
//Receive message from the server
//Message is stored in the br.readLine()
brr = new BufferedReader(new InputStreamReader(socket.getInputStream()));
img = brr.readLine();
Log.d("Image", img);//yeh byte[] display karta h
final ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(img.getBytes());
arrayInputStream.reset();
this.socket.close();
runOnUiThread(new Runnable() {
#Override
public void run() {
Glide.with(ParentalControl.this)
.load(bitmap)
.asBitmap()
.into(mivScreenShot);
}
});
if(bitmap!=null)
{
Log.d(DebuggString,"Bitmap is not null "); // oh ok koi nai
}
else
{
Log.d(DebuggString,"Bitmap is null");
}
}
catch (IOException e )
{
e.printStackTrace();
}
}
}.start();
}
Here I am attaching the logcat screenshot url: https://i.imgur.com/167Vje3.png
mainWriter = new BufferedWriter(new OutputStreamWriter(socket2.getOutputStream()));
mainWriter.write(java.util.Arrays.toString(ar));
You cannot use writers and strings to send a jpg image as those are for text only. Do away with them. Do away with the ByteOutputStream too as you can just directly compress the bitmap to the outputstream of the socket.
Further check how many bytes you send and how many are received.
That was for the server. Also on the receiving side you cannot use readers and strings.
I am implementing a server in java which recieves images from an android application. basically it is recieving image from android emulator but not from android device. This all process of recieving an image from android emulator or android device is done on localhost.
here is my code of the server.
public class Server {
private static ServerSocket serverSocket;
private static Socket clientSocket;
private static InputStreamReader inputStreamReader;
private static BufferedReader bufferedReader;
private static String message;
private static byte[] image;
public static void main(String[] args) throws UnknownHostException, IOException {
try {
serverSocket = new ServerSocket(4000); // Server socket
} catch (IOException e) {
System.out.println("Could not listen on port: 4000");
}
System.out.println("Server started. Listening to the port 4000");
while (true) {
clientSocket = serverSocket.accept(); // accept the client connection
inputStreamReader = new InputStreamReader(clientSocket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader); // get the client message
DataInputStream inputFromClient = new DataInputStream(clientSocket.getInputStream());
int count = inputFromClient.available();
System.out.println(count);
image = new byte[count];
inputFromClient.readFully(image);
final BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(image));
ImageIO.write(bufferedImage, "jpg", new File("image.jpg"));
}
}
Exception
Exception in thread "main" javax.imageio.IIOException: Error reading PNG image data
at com.sun.imageio.plugins.png.PNGImageReader.readImage(PNGImageReader.java:1308)
at com.sun.imageio.plugins.png.PNGImageReader.read(PNGImageReader.java:1577)
at javax.imageio.ImageIO.read(ImageIO.java:1448)
at javax.imageio.ImageIO.read(ImageIO.java:1352)
at server.Server.main(Server.java:39)
Caused by: java.io.EOFException: Unexpected end of ZLIB input stream
at java.util.zip.InflaterInputStream.fill(InflaterInputStream.java:240)
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)
at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
at java.io.DataInputStream.readFully(DataInputStream.java:195)
at com.sun.imageio.plugins.png.PNGImageReader.decodePass(PNGImageReader.java:1092)
at com.sun.imageio.plugins.png.PNGImageReader.decodeImage(PNGImageReader.java:1196)
at com.sun.imageio.plugins.png.PNGImageReader.readImage(PNGImageReader.java:1301)
... 4 more
Java Result: 1
I am getting an exception of javax.imageiio.exception in case of sending an image from android device but for android emulator it is working fine. Kindly help me out plz. Thank You.
Your main problem is located in this line:
int count = inputFromClient.available();
It returns the number of bytes that are already received at that time. However there may be more bytes waiting to be transferred on the server side.
Therefore the transmitted image is truncated/incomplete when you try to load it.
You have now two choices:
Before transferring the image data send an integer containing the length of the data
If only one image is transferred close the stream on client side after the image has been written. On server side you now have to read until you reach the end of the stream.
i have a program which accepts connection from a phone that sends a byte array, i am able to test the connection when it is made , however how do i know that i am actually receiving something? how can i "see" if any thing is being sent over the socket. Because from my code below i am not able to have the resulting file "saved.jpg" created. Does this mean that it did not receive anything?
public class wpsServer {
//vars
private int svrPort = 3334;
private ServerSocket serverSocket;
private Image image = null;
public wpsServer()
{
try {
serverSocket = new ServerSocket(svrPort);
System.out.println("Server started on "+svrPort);
}
catch (IOException e) {
System.out.println("Could not listen on port: "+svrPort);
System.exit(-1);
}
}
public void listenForClient()
{
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
if(clientSocket.isConnected())
System.out.println("Connected");
byte[] pic = getPicture(clientSocket.getInputStream());
InputStream in = new ByteArrayInputStream(pic);
BufferedImage image = ImageIO.read(in);
File outputfile = new File("saved.jpg");
ImageIO.write(image, "jpg", outputfile);
}
catch (IOException e) {
System.out.println("Accept failed: "+svrPort);
System.exit(-1);
}
}
public byte[] getPicture(InputStream in) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int length = 0;
while ((length = in.read(data))!=-1) {
out.write(data,0,length);
}
return out.toByteArray();
} catch(IOException ioe) {
//handle it
}
return null;
}
}
The in.read call will only return -1 if the other end closes the socket. While the socket is alive, that call will block until more data is available.
What you need to do is change your "protocol": the client should send the array size first, then the data. The server should read that length, and stop reading the file when that's done (go back to waiting for the next file for instance).
I'm writing an android app that sends an image to a server running a java app, and it's working in a very weird way!
Here is what I do
Compile and run the Java app on the desktop with the receive part that acts as server
Compile,deploy and run the android part that has to send the image to the server. The android app finishes execution but the java app doesn't
Run the android app activity that has the code to send the image AGAIN, and this time, the android app progress dialog gets stuck, BUT, the java app finishes execution and also the image is transferred d successfully...
Following is the code for the RECEIVE part of the Java app:
class ProjectServer
{
ServerSocket serSock;
Socket sock;
BufferedReader in;
PrintWriter out;
public static void main(String ar[])
{
try
{
ProjectServer cs=new ProjectServer();
cs.startServer();
}
catch(Exception e)
{
}
}
public void startServer()
{
try
{
serSock=new ServerSocket(8070);
System.out.println("Waiting for client...");
sock=serSock.accept();
System.out.println("Connections done");
//Accept File
System.out.println("Connected");
//receive code
int filesize=450660;
int bytesRead;
int current=0;
// receive file
byte [] mybytearray = new byte [filesize];
InputStream is = sock.getInputStream();
FileOutputStream fos = new FileOutputStream("C:\\Project Server\\Capture.png");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do {
bytesRead =
is.read(mybytearray, current, (mybytearray.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > -1);
bos.write(mybytearray, 0 , current);
bos.flush();
System.out.println("end-start");
}
catch(Exception e)
{
System.out.println(e);
e.printStackTrace();
}
}
}
Following is the code for the SEND part on the Android app:
package com.site.custom;
public class Act2 extends Activity
{
private ProgressDialog pd;
private String serverIP="58.146.100.187";
private BufferedReader in;
private PrintWriter out;
private String path;
private Socket cliSock;
public void onCreate(Bundle onCreateInstance)
{
super.onCreate(onCreateInstance);
setContentView(R.layout.act2);
this.setTitle("This has started");
path=getIntent().getStringExtra("path");
//Establish Connection
try
{
cliSock=new Socket(serverIP,8070);
in=new BufferedReader(new InputStreamReader(cliSock.getInputStream()));
((TextView)findViewById(R.id.tview)).setText(path);
}
catch(Exception e)
{
Log.v("MERA MSG",e.toString());
}
//Send file
ProgressDialog pd=ProgressDialog.show(this, "Sending image", "Image chosen:"+path.substring(path.lastIndexOf("//")+1),false,true);
try
{
File myFile = new File (path);
System.out.println((int)myFile.length());
byte[] mybytearray = new byte[450560];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
OutputStream os = cliSock.getOutputStream();
System.out.println("Sending...");
os.write(mybytearray,0,mybytearray.length);
os.flush();
System.out.println("Completed");
pd.dismiss();
System.out.println("Done");
}
catch(Exception e)
{
Log.v("MERA MSG",e.toString());
}
}
}
You're not closing any of the connections. Your Server is probably waiting until the connection is closed before it knows that data has finished being sent. When your Client runs the second time, the first connection is probably closed automatically by Android, this allowing your Server to process the image. However, if your Server doesn't process the image fast enough, maybe your Client gets 'stuck' on the second run because its waiting for the successful port connection to the Server but the Server is busy.
Long story short, how about you try to close() the Client connection when you're finished with it. Calling flush() doesn't really tell anything to the Server to say that the data has finished being sent.
If you want the socket to stay open even though you close the OutputStream, you could write a custom Socket that just overwrites the close() method, something like this...
public class MySocket extends Socket {
public MySocket(String ipAddress, int port){
super(ipAddress,port);
}
public void close(){
// do nothing
}
public void reallyClose(){
super.close();
}
}
In your code, change cliSock=new Socket(serverIP,8070); to cliSock=new MySocket(serverIP,8070);
When you call OutputStream.close(), it calls close() on MySocket, but as you can see it doesn't actually do anything. When you've completely finished with the Socket, you can call MySocket.reallyClose(); and it'll close it off properly.