Android File transfer including Exif data - java

I'm trying to transfer some image files from an android phone, over a socket, to a server. The only way I've found to do this on android so far is using a FileInputStream to read the image as a byte array and send this over the socket to be reconstructed on the server side. This works well, unfortunately Android (or java?) does not allow Metadata, in my case exif data, to be included in a FileInputStream. This means that my exif data is missing once the images are on the server.
I've tried to solve this issue using both ExifInterface, which doesn't seem to be able to read a lot of the exif data I need, and the Metadata library. The metadata library does seem to get all the exif data I want but I can't figure out how to write it out as bytes that can be sent over my stream, it only has a toString which gets rid of some of the data that needs to be transferred.
Ideally I'd love a way to transfer the file with it's metadata, however I'd be happy with a way to turn Metadata tags into bytes which I can add to my socket's output stream.
Here is the code which uploads files over the socket
FileInputStream in = new FileInputStream(lastSavedPath);
byte[] buffer = new byte[1024];
int length = 0;
while ((length = in.read(buffer, 0, buffer.length)) != -1){
outputStream.write(buffer, 0, length);
}
ExifInterface exifInterface = new ExifInterface(lastSavedPath);
Metadata metadata = ImageMetadataReader.readMetadata(new File(lastSavedPath));
for (Directory directory : metadata.getDirectories()){
for (Tag tag : directory.getTags()){
Log.d("Socket Listener", tag.toString());
if (tag.toString().indexOf("Exif")>=0)
Log.d("Socket exif", "Data"+exifInterface.getAttribute(tag.getTagName()));
}
}
outputStream.flush();
Log.d("Socket Listener", "Data has been sent");
in.close();
socket.close();

The issue here wasn't with android at all. I had read in another thread that the android FileInputStream did not include metadata but that was not the case. I believe now the issue was in my server side code. I've fixed the issue with the following code:
Server side (Needs to be in a try catch):
socket = new Socket(args[0], 8888);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF(args[1]);
System.out.println("Saving image");
FileOutputStream fileout = new FileOutputStream("/home/jamie/Documents/UMDSummer16/Thermal/TemporalAnalysisSensor/SocketTest/"+args[2]);
byte[] bytes = new byte[1024];
int count;
while ((count = dataInputStream.read(bytes)) > 0){
fileout.write(bytes);
}
fileout.close();
dataInputStream.close();
Android side (also in a try catch):
FileInputStream in = new FileInputStream(lastSavedPath);
byte[] buffer = new byte[1024];
int length = 0;
while ((length = in.read(buffer, 0, buffer.length)) != -1) {
outputStream.write(buffer, 0, length);
}
outputStream.flush();
Log.d("Socket Listener", "Data has been sent");
in.close();
socket.close();

Related

Java: Transferring File over TCP

I'm in the midst of trying to send a file, and in particular large files, from server to client. I can send small files but atm large files do not work.
Server
Socket socket = serverSocket.accept();
byte[] data = new byte[(int)myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(data, 0, data.length);
OutputStream oStream = socket.getOutputStream();
oStream.write(data, 0, data.length);
Client
byte[] data = new byte[4096];
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream("output.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = is.read(data, 0, data.length);
int counter = bytesRead;
// while (-1 != (bytesRead = is.read(data, 0, data.length)))
// {
// bos.write(data, 0, bytesRead);
// }
bos.write(data, 0, bytesRead);
With this code i'm able to transfer a simple text file successfully. With the commented out section uncommented (and excluding the last line) i thought i'd still be able to send a simple text file and in addition large files like a 200mb video. Obviously, it failed and here i am. Hope someone could give me a hand.
EDIT: Error with while loop (and no last line) is that nothing is written in the txt file
Get rid of the first read and the last write and just use the code that is commented out. That's the only code that actually works.

How to transfer file info and multiple files over a socket in Java?

I have one client and one server communicating with each other via TCP sockets. The client would like to transfer two files and some description of the files to the server. I would like to design a protocol that once a socket is established between the client and the server, the server would expect to receive the file description first and then the two files. Currently, with the following code, the server can receive the description but fails to distinguish the two files (the two files transferred from the client are merged into one single file at the server). I found similar threads on this issue. But they separately discussed "file info + one single file" and "multiple file without pre-file-info". Please give me a hint on resolving this issue. Many thanks.
Sever-side code
dis = new DataInputStream(clientSocket.getInputStream());
callInfo = dis.readUTF();
callInfos = callInfo.split(" ");
FileOutputStream fos = new FileOutputStream(File1);
byte[] buffer = new byte[clientSocket.getReceiveBufferSize()];
int bytesReceived = 0;
while ((bytesReceived = dis.read(buffer)) > 0)
fos.write(buffer, 0, bytesReceived);
fos.flush();
fos.close();
fos = new FileOutputStream(File2);
while ((bytesReceived = dis.read(buffer)) > 0)
fos.write(buffer, 0, bytesReceived);
fos.flush();
fos.close();
Client-side code
String fileIno = "fileIno";
byte[] buffer = new byte[socket.getSendBufferSize()];
int bytesRead = 0;
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF(fileInfo);
FileInputStream file = new FileInputStream(File1);
while ((bytesRead = file.read(buffer)) > 0)
dos.write(buffer, 0, bytesRead);
dos.flush();
file.close();
file = new FileInputStream(File2);
while ((bytesRead = file.read(buffer)) > 0)
dos.write(buffer, 0, bytesRead);
dos.flush();
file.close();
Design your protocol such that the "file description" information includes the number of bytes in each file. Then you will know where the first file begins and ends and where the second file begins and ends.

Send image from android part and receive it from pc, but the image is corrupted

I'm trying to send an jpeg image from my android phone through socket and from the PC part, get the sent data and store it in an jpg file.
I'm pretty sure that I configured the socket correctly, as I can download data (binary file) from PC to android and save it correctly.
I can also read the stream which is sent from android to PC. The packet length and header information are exactly what I expect.
The problem is in reading image data. I'm getting same size for image data but when I save it to .jpg file, it is corrupted and I can not view it.
Here is my Android code that tries to send image file after sending header information:
try{
//packagesize is header information which is sent in advance
index.putInt(packagesize);
byte c[]= {index.get(3),index.get(2),index.get(1),index.get(0)};
InputStream jpgimage = new FileInputStream(fileimage);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
int writeBytes = 0,len = 0;
byte buffer[] = new byte[1024];
while((len = jpgimage.read(buffer,0,buffer.length))!=-1)
{
writeBytes+=len;
dataOutputStream.write(buffer,0,len);
}
dataOutputStream.flush();
jpgimage.close();
dataInputStream.close();
dataOutputStream.close();
...
...
...
}
catch statements here
This is the receiving code in the PC part:
// after reading header information I try to read image data
char *buff = malloc(sizeof(char) * jpeg_length);
unsigned int byteCount = 0;
unsigned int byteCount = 0;
do
{
int ret = recv(socket, buff+readBytes, jpeg_length-readBytes, 0);
if (ret <= 0)
{
fprintf(stderr,"Error receiving jpeg file.\n");
fclose( output );
return 106;
}
readBytes += ret;
fwrite(buff, sizeof(char), readBytes, output);
}
while (readBytes < jpeg_length);
fclose( output );
I also have to mention that the receiving part is working fine when I send image data with PC client application which is pure C++.
Is there any idea about what is the problem and why I get corrupted image sending from android device?
Appreciate it.
Edited
I add this the to android application for testing if the sending bytes can form a good image or not? I saved the image and it was OK.
int writeBytes = 0,len = 0;
byte buffer[] = new byte[1024];
// Here I save all sending bytes to an image called test.jpg
String path = "sdcard/download/images/test.jpg";
FileOutputStream stream = new FileOutputStream(path);
while((len = jpgimage.read(buffer,0,buffer.length))!=-1)
{
writeBytes+=len;
stream.write(buffer);
dataOutputStream.write(buffer,0,len);
dataOutputStream.flush();
}
stream.flush();
dataOutputStream.flush();
jpgimage.close();
dataInputStream.close();
dataOutputStream.close();
I think you should use Bitmap class to convert you image to ByteBuffer and then send it across and on the other end convert ByteBuffer to image.
On Sender Side
Bitmap bitmap = BitmapFactory.decodeFile("ImageD2.jpg");
int bytes = bitmap.getByteCount();
ByteBuffer buffer = ByteBuffer.allocate(bytes);
bitmap.copyPixelsToBuffer(buffer);
byte[] array = buffer.array();
Now you can send byte[] as normal data.
On receiving side
receive the array normally and convert it back to Bitmap
Bitmap bitmap = BitmapFactory.decodeByteArray(array , 0, array .length);
for more information you can read following questions
Converting bitmap to byteArray android
How to convert byte array to Bitmap
I found the solution for that. The problem was from Android side. So I did the following changes:
I changed DataOutputStream and DataInputStream to BufferedOutputStream and BufferedInputStream respectively :
try{
//packagesize is header information which is sent in advance
index.putInt(packagesize);
byte c[]= {index.get(3),index.get(2),index.get(1),index.get(0)};
InputStream jpgimage = new FileInputStream(fileimage);
dataOutputStream = new BufferedOutputStream(socket.getOutputStream());
dataInputStream = new BufferedInputStream(socket.getInputStream());
int writeBytes = 0,len = 0;
byte buffer[] = new byte[1024];
while((len = jpgimage.read(buffer,0,buffer.length))!=-1)
{
writeBytes+=len;
dataOutputStream.write(buffer,0,len);
}
dataOutputStream.flush();
jpgimage.close();
dataInputStream.close();
dataOutputStream.close();
...
...
...
}
catch statements here

Transfering file over a socket in ftp protocol

I have a problem to send a file(not necessarily a txt file) over a socket.I have 2 classes:Server,Client.When I read from a socket output stream and want to write the bytes in a file,it looks working but when i open the file it has nothing.(corrupted showing the size=0 kb).I also want it to transfer all kind of file over a socket.I don't want to use appache commons net.
Here is my code
Server class
FileOutputStream toFile1 = new FileOutputStream(f);
BufferedOutputStream toFile= new BufferedOutputStream(toFile1);
BufferedInputStream bis=new BufferedInputStream(incoming.getInputStream());
byte[]buffer=new byte[2048];
int bytesRead=0;
while((bytesRead = bis.read(buffer)) >= 0)
{
toFile.write(buffer, 0, bytesRead);
}
toFile.close();
toFile1.close();
bis.close();
out.println("226 Connection Closed");
out.flush();
}
Client class
BufferedOutputStream output = new BufferedOutputStream(socket.getOutputStream());
byte[] buffer = new byte[60*2024];
int bytesRead = 0;
while ((bytesRead = input.read(buffer,0,60*1024)) != -1) {
output.write(buffer, 0, bytesRead);
}
The only way that can happen with that code is if you are sending a zero length file, or maybe reading from a file input stream that is already positioned at EOF, or else you are looking at the wrong file afterwards.

Java urlConnection, saving audio file to server?

I've seen examples with text files but is saving an audio file directly to a server done the same way with URLConnection?
Yes, the same. Although make sure you use a binary output stream to write the content to disk.
Something like:
URLConnection conn = new URL("http://www.gravatar.com/avatar/fd9e8761fad999a1bf1e095fc8f53ffe?s=32&d=identicon&r=PG")
.openConnection();
InputStream is = conn.getInputStream();
FileOutputStream outstream = new FileOutputStream("/tmp/myfile");
byte[] buffer = new byte[4096];
int len;
while ((len = is.read(buffer)) > 0) {
outstream.write(buffer, 0, len);
}
outstream.close();
is.close();
The example uses your gravatar, but same difference.

Categories