Sending File using sockets in android - android

I know basic socket programming.
I have a code to send strings using sockets in android.
I want to learn how to send a file (MP3,image etc) using sockets between two phones.

This is some code to send a file. It should work just like you would expect outside of Android. I knew I was sending files that were relatively small, so you might want to make more than one pass through a buffer. The File "f" in my example should just be replaced with the File that contains your MP3 or Image or whatever you want to send.
public void sendFile() throws IOException{
socket = new Socket(InetAddress.getByName(host), port);
outputStream = socket.getOutputStream();
File f = new File(path);
byte [] buffer = new byte[(int)f.length()];
FileInputStream fis = new FileInputStream(f);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(buffer,0,buffer.length);
outputStream.write(buffer,0,buffer.length);
outputStream.flush();
}

Related

Creating File With String Object

im writing a socket program which send and receive strings.
Im trying to build a file using this received strings that are sending from other side.
this is exactly done with text files but in others such an image file doesn't work and when complete, the image does not open!
in receiver:
file = new File(dir,FileName);
fOut = new FileOutputStream(file);
dos = new DataOutputStream(fOut);
and when a msg received:
dos.write(msg.getBytes("UTF-8"));
in sender:
File file = new File(FilePath);
InputStream is = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(is);
...
isr.read(inputBuffer);
I have Tried this solution but the problem didn't fixed:
Changing the UTF-8 to ISO-8859-1
using output stream writer instead of data output stream.
trying with smaller pictures than text file.
ByteArrayOutputStream is useful converting bitmap to byte array.
after then, you using BitmapFactory, decodeByteArray is converting byte to bitmap.

Is there a way I can try a file upload (image) without actually writing the server side code?

I haven't wrote any server side code till now. Is there any way I can try writing an android program where I can write the file being uploaded from the mobile to a remote server?
Additional details:-
My code -
private void sendToRemoteServer(){
Socket client;
FileInputStream fileInputStream;
BufferedInputStream bufferedInputStream;
OutputStream outputStream;
try{
client = new Socket("10.0.2.2",444);
byte[] myByteArray = new byte[(int)mFile.length()];
fileInputStream = new FileInputStream(mFile);
bufferedInputStream = new BufferedInputStream(fileInputStream);
bufferedInputStream.read(myByteArray, 0, myByteArray.length); //read the file
outputStream = client.getOutputStream();
outputStream.write(myByteArray, 0, myByteArray.length); //write file to the output stream byte by byte
outputStream.flush();
bufferedInputStream.close();
outputStream.close();
client.close();
}catch(UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
All I need to make sure is that android doesn't run out of memory exception.
There are several options. One is to use webDAV or FTP on server. But nowadays there is a lot of file storage services which you can access with RESTful API like Amazon S3
It seems you want to mock a Server. https://stackoverflow.com/questions/393099/mocking-http-server is a good point to start from.

Android Java TCP Client Server File Transfer

Edit*
I have successful on the client server. Now I am doing a file transferring between 2 emulators. The file did transfer between the emulators, but I notice that the file size received is not the same as the original file. For example, A.jpg size is 900KB, but the received file is less than 900KB. I checked the file transfer size, found that there were some data(byte) lost when transferring. How is this happening?
Here's the code:
Client (Send File)
File myFile = new File ("/mnt/sdcard/Pictures/A.jpg");
FileInputStream fis = new FileInputStream(myFile);
OutputStream os = socket.getOutputStream();
int filesize = (int) myFile.length();
byte [] buffer = new byte [filesize];
int bytesRead =0;
while ((bytesRead = fis.read(buffer)) > 0) {
os.write(buffer, 0, bytesRead);
//Log display exact the file size
System.out.println("SO sendFile" + bytesRead);
}
os.flush();
os.close();
fis.close();
Log.d("Client", "Client sent message");
socket.close();
Server (Receive File)
FileOutputStream fos = new FileOutputStream("/mnt/sdcard/Pictures/B.jpg");
#SuppressWarnings("resource")
BufferedOutputStream bos = new BufferedOutputStream(fos);
InputStream is = clientSocket.getInputStream();
byte[] aByte = new byte[1024];
int bytesRead;
while ((bytesRead = is.read(aByte)) != -1)
{
bos.write(aByte, 0, bytesRead);
//Log display few parts the file size is less than 1024. I total up, the lost size caused the file received is incomplete
System.out.println("SO sendFile" + bytesRead);
}
clientSocket.close();
*Edit 2
While I surfed around google, I found that .read(buffer) does not guarantee read the full size(byte) of the file. Hence, the received file always lost some bytes (like space, empty character). To solve this, send the file size first to inform the receiver, then only start transfer the file.
NetworkOnMainThreadException occurs because you have to use AsyncTask
NullPointerException occurs because you are trying to use PrintWriter with the result of Sockets. As you have got nothing with Sockets you get this error.
The NetworkOnMainThreadException tells you what you are doing wrong.
You need to put the network stuff into a separate Thread (or AsyncTask or similar).
You can not call any server operation on Main Thread in Android.
In Android O.S 4.0 and above this will directly cause to NetworkOnMainThreadException. You have 2 choices :
1) Either to use AsyncTask to call your every server operation.
2) Or Use User defined Thread for any type of server operation.
I was also struggling with this Exception, only in OS version above 4.0 devices, So you can not ignore these small needs of Android.

Android: Extra bytes in file transferred to device

So, I have a simple Android app that connects to a Java Server application using Sockets.
Specifically, I want to be able to send a file from the Server application to the Android app and then store that file in internal memory on the device.
The basis of the server code for transferring the file is:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(System.getProperty("user.home"), "text.txt")));
BufferedOutputStream bos = new BufferedOutputStream(clientSocket.getOutputStream());
byte buffer[] = new byte[1024];
int read;
while ((read = bis.read(buffer)) != -1) {
bos.write(buffer, 0, read);
}
bos.flush();
bos.close();
and the Client code to receive the file is as follows:
BufferedInputStream bis = new BufferedInputStream(clientSocket.getInputStream());
BufferedOutputStream bos = new BufferedOutputStream(openFileOutput("text.txt", Context.MODE_PRIVATE));
byte buffer[] = new byte[1024];
int read;
while ((read = bis.read(buffer)) != -1) {
bos.write(buffer, 0, read);
}
bos.flush();
bos.close();
The code appears to work fine when the client code is in a standard Java application, that is, the file sends successfully from server to client.
The problem arises when I use this code in an Android app. (Note: I use a standard FileOutputStream in the standard Java app instead of the
openFileOutput("text.txt", Context.MODE_PRIVATE))
line above).
For example purposes, the file I am transferring is a simple UTF-8 text file, which contains a single string
This is a text file.
However, when I pull this file I have copied to the emulator, from the "/data/data//files" folder on the emulator, there are an extra couple of bytes at the top of the file so the content is now
¨ÌThis is a text file.
I have no idea why this is happening and it has me stumped. I think the problem might be related to the line:
BufferedOutputStream bos = new BufferedOutputStream(openFileOutput("text.txt", Context.MODE_PRIVATE));
but I can't quite figure it out.
Any suggestions as to what I am doing wrong would be most helpful.
Thank you in advance

android add filename to bytestream

im trying to send a file in android through sockets. i want to add the filename with the bytestream and then send it to the server. how do i do that? and then how do i seperate the filename on the receiving side?
this is the code to send file :
Log.i("SocketOP", "sendFILE-1");
File f = new File(path);
String filename=path.substring(path.lastIndexOf("/")+1);
System.out.println("filename:"+filename);
fin.filename = "~"+filename;
BufferedOutputStream out = new BufferedOutputStream( socket.getOutputStream() );
FileInputStream fileIn = new FileInputStream(f);
Log.i("SocketOP", "sendFILE-2");
byte [] buffer = new byte [(int)f.length()];
System.out.println("SO sendFile f.length();" + f.length());
int bytesRead =0;
while ((bytesRead = fileIn.read(buffer)) > 0) {
out.write(buffer, 0, buffer.length);
System.out.println("SO sendFile" + bytesRead +filename);
}
out.flush();
out.close();
fileIn.close();
Log.i("SocketOP", "sendFILE-3");
If this is your own protocol then you create a data packet that separate the two sections (filename and data). You need to denote clearly the separation via a particular boundary.
On the server, since you understand the protocol, the server will read back the whole data packet and it will separate the filename and data based on the given boundary.
MIME data format use exactly this kind of data exchange and widely use with HTTP protocol. If you use the same MIME Data Format, another advantage is you could use third party library to encode and decode your data such as HttpMime
Below is the rough code to format the data using MIME data and send it through Socket
File f = new File(path);
BufferedOutputStream out = new BufferedOutputStream( socket.getOutputStream() );
String filename=path.substring(path.lastIndexOf("/")+1);
// create a multipart message
MultipartEntity multipartContent = new MultipartEntity();
// send the file inputstream as data
InputStreamBody isb = new InputStreamBody(new FileInputStream(f), "image/jpeg", filename);
// add key value pair. The key "imageFile" is arbitrary
multipartContent.addPart("imageFile", isb);
multipartContent.writeTo(out);
out.flush();
out.close();
Note that you would need org.apache.http.entity.mime.MultipartEntity and org.apache.http.entity.mime.content.InputStreamBody from HttpMime project. On the server, you need MIME parser that would get back the filename and all the bytes content
To read the inputstream back on the server, you would need a class to parse the MIME message. You shouldn't have to write the parser yourself as MIME is a popular message format already unless you want to learn about the MIME message structure.
Below is the sample code using MimeBodyPart that is part of JavaMail.
MimeMultipart multiPartMessage = new MimeMultipart(new DataSource() {
#Override
public String getContentType() {
// this could be anything need be, this is just my test case and illustration
return "image/jpeg";
}
#Override
public InputStream getInputStream() throws IOException {
// socket is the socket that you get from Socket.accept()
BufferedInputStream inputStream = new BufferedInputStream(socket.getInputStream());
return inputStream;
}
#Override
public String getName() {
return "socketDataSource";
}
#Override
public OutputStream getOutputStream() throws IOException {
return socket.getOutputStream();
}
});
// get the first body of the multipart message
BodyPart bodyPart = multiPartMessage.getBodyPart(0);
// get the filename back from the message
String filename = bodyPart.getFileName();
// get the inputstream back
InputStream bodyInputStream = bodyPart.getInputStream();
// do what you need to do here....
You could download JavaMail from Oracle Website which also has dependency on Java Activation Framework

Categories

Resources