I want to let the user download a file from my android app with the web browser on his computer (in local network).
At first I wrote the code for this feature in eclipse on my computer and it worked fine. But when I try to run it in an android app (the file is copied from the assets path) I am not able to download the file anymore. Firefox just tells me that it couldnt download because the source file could not be read.
This ist my code in the app. It doesnt throw any errors.
public class test implements Runnable {
public boolean running = true;
ServerSocket servsock = null;
Context context;
String filename = "test.jar";
public test(Context con){
this.context=con;
}
public Integer createSocketandStart(){
for (int i=1234; i<2000; ++i){
try{
servsock = new ServerSocket(i);
servsock.setSoTimeout(1000000);
new Thread(this).start();
return i;
}catch(Exception e){
System.out.print("socket error");
}
}
return null;
}
public void run(){
File f= new File(context.getFilesDir(), filename);
try {
InputStream is = context.getAssets().open(filename);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
FileOutputStream fos = new FileOutputStream(f);
fos.write(buffer);
fos.close();
} catch (Exception e) { throw new RuntimeException(e); }
while (running) {
try {
Socket connection = servsock.accept();
OutputStream out = new BufferedOutputStream(connection.getOutputStream());
PrintStream pout = new PrintStream(out);
InputStream file = new FileInputStream(f);
pout.print("HTTP/1.0 200 OK\r\n" +
"Content-Type: application/octet-stream\r\n" +
"Content-Disposition: attachment; filename=\"" + filename + "\"\r\n" +
"Date: " + new Date() + "\r\n" +
"Server: FileServer 1.0\r\n\r\n");
byte[] buffer = new byte[1000];
while (file.available() > 0) {
out.write(buffer, 0, file.read(buffer));
}
out.flush();
if (connection != null) connection.close();
file.close();
pout.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Related
I am saving a pdf file that im am receiving from server via method:
private boolean writeResponseBodyToDisk(ResponseBody body) {
try {
File futureStudioIconFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "order.pdf");
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
long fileSize = body.contentLength();
long fileSizeDownloaded = 0;
inputStream = body.byteStream();
outputStream = new FileOutputStream(futureStudioIconFile);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
Log.d(TAG, "file download: " + fileSizeDownloaded + " of " + fileSize);
}
outputStream.flush();
return true;
} catch (IOException e) {
return false;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
return false;
}
}
I did manage to save it on the device though as much as i understood i can't open it directly after the download because it's downloading from a item click in a adapter. Anyway, I made it so that after the download it changes the page to another activity where i should be able to open it, though it still fails. Code I am using in the activity:
String path = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) + "/order.pdf";
File file=new File(path);
if(file.canRead())
{
pdfView.fromFile(file).defaultPage(1).onLoad(new OnLoadCompleteListener() {
#Override
public void loadComplete(int nbPages) {
Toast.makeText(PdfActivity.this, String.valueOf(nbPages), Toast.LENGTH_LONG).show();
}
}).load();
}
Since the code should be correct, I tried a lot of variations of getting the path to the pdf, none seemed to work. Is the issue in the path or is it a whole other problem?
Edit: It can't read the file in if(file.canRead())
I'm trying to send multiple files from client to server using socket but when I click upload button it adds only one file second
Your copyFile() is not suitable for network transmissions.
You need to get rid of the two close() calls inside of copyFile(). On the client side, out.close() is closing the socket after the 1st file has been sent. On the server side, InputStream.close() is closing the socket after the 1st file has been received. It is the caller's responsibility to close the streams it passes to copyFile(), it is not copyFile()'s responsibility.
More importantly, for each file the client wants to send, copyFile() is not sending the file's byte count before sending the file's actual bytes, to indicate where each file ends and the next begins. So, on the server side, copyFile() does not know when to stop reading from the inputStream and will just keep reading endlessly until the connection is closed/broken.
As-is, copyFile() may work for copying files from one folder to another on the local system, but it is not suitable for copying files over a TCP network.
Try this instead:
Client side:
try {
socket.bind(null);
socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
Log.d(TAG, "Client socket - " + socket.isConnected());
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
DataOutputStream dos = new DataOutputStream(bos);
dos.writeInt(fileUri.size());
for(String file : fileUri)
{
//long length = file.length();
//dos.writeLong(length);
String name = file;
dos.writeUTF(name);
File f = new File(file);
sendFile(f, dos);
}
dos.close();
Log.d(TAG, "Client: Data written");
}
catch (IOException e) {
Log.e(TAG, e.getMessage());
}
finally {
if (socket != null) {
if (socket.isConnected()) {
try {
socket.close();
}
catch (IOException e) {
// Give up
e.printStackTrace();
}
}
}
}
void sendFile(File in, DataOutputStream out) throws IOException {
long fileLength = in.length();
out.writeLong(fileLength);
FileInputStream fis = new FileInputStream(in);
BufferedInputStream bis = new BufferedInputStream(fis);
byte buf[] = new byte[1024];
int len;
while (fileLength > 0) {
len = bis.read(buf);
if (len == -1) throw new IOException();
out.write(buf, 0, len);
fileLength -= len;
}
}
Server side:
try {
ServerSocket serverSocket = new ServerSocket(8988);
Socket client = serverSocket.accept();
BufferedInputStream bis = new BufferedInputStream(client.getInputStream());
DataInputStream dis = new DataInputStream(bis);
int filesCount = dis.readInt();
File[] files = new File[filesCount];
for(int i = 0; i < filesCount; i++)
{
Log.d(TAG, "doInBackground: " + filesCount);
//long fileLength = dis.readLong();
String fileName = dis.readUTF();
files[i] = new File(context.getExternalFilesDir("received"), Long.toString(System.currentTimeMillis()) + ".mp4" );
Log.d(TAG, "doInBackground: 1" );
File dirs = new File(context.getPackageName() + files[i].getParent());
Log.d(TAG, "doInBackground: 2" );
if (!dirs.exists()) dirs.mkdirs();
files[i].createNewFile();
Log.d(TAG, "server: copying files " + files[i].toString());
receiveFile(dis, files[i]);
}
serverSocket.close();
return "done";
}
catch (IOException e) {
Log.e(TAG, e.getMessage());
return null;
}
void receiveFile(DataInputStream in, File out) throws IOException {
long fileLength = in.readLong();
FileOutputStream fos = new FileOutputStream(out);
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte buf[] = new byte[1024];
int len;
while (fileLength > 0) {
len = (fileLength >= 1024) ? 1024 : (int) fileLength;
len = in.read(buf, 0, len);
if (len == -1) throw new IOException();
bos.write(buf, 0, len);
fileLength -= len;
}
}
How to receive original content and file name from server side code.
Client Code
public void send1(Socket socket)
{
try
{
dataOutputStream = new DataOutputStream(socket.getOutputStream());
File file = new File(Environment.getExternalStorageDirectory().toString() + "/" + "temp.txt");
FileInputStream fis = new FileInputStream(file);
//write file length
dataOutputStream.writeLong(file.length());
Log.i("File Size", "" + file.length());
//write file names
dataOutputStream.writeUTF(file.getName());
Log.i("File Name", "" + file.getName());
//write file to dos
byte[] buf = new byte[4092];
int n = 0;
while((n = fis.read(buf)) != -1)
{
Log.i("length bytes", "" + n);
dataOutputStream.write(buf, 0, n);
}
dataOutputStream.flush();
dataOutputStream.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
File Name as temp.txt and Content as Hello
Server Code
public void receive1(Socket socket)
{
try
{
inputStream = socket.getInputStream();
dataInputStream = new DataInputStream(inputStream);
File file = new File(Environment.getExternalStorageDirectory().toString() + "/" + "test.txt");
FileOutputStream fos = new FileOutputStream(file);
int n = 0;
byte[] buf = new byte[4092];
//read file name
/*String fileName = "";
try
{
fileName = dataInputStream.readUTF();
}
catch (Exception e)
{
e.printStackTrace();
}
Log.i("File Name", "" + fileName);*/
//read file size
long fileSize = 0;
try
{
fileSize = dataInputStream.readLong();
}
catch (Exception e)
{
e.printStackTrace();
}
Log.i("File Size", "" + fileSize);
//read file
while((n = dataInputStream.read(buf)) != -1)
{
Log.i("length bytes", "" + n);
fos.write(buf, 0, n);
}
fos.flush();
fos.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
File Name as test.txt and Content as temp.txtHello.
In this test.txt file, contains temp.txt. I am not getting file name from dataInputStream.readUTF().
Where I mistaken code...
If I called readUTF() method, then I am getting the Exception
Exception as
java.io.EOFException
at libcore.io.Streams.readFully(Streams.java:83)
at java.io.DataInputStream.readFully(DataInputStream.java:99)
at java.io.DataInputStream.decodeUTF(DataInputStream.java:178)
at java.io.DataInputStream.decodeUTF(DataInputStream.java:173)
at java.io.DataInputStream.readUTF(DataInputStream.java:169)
You wrote the Long before the String in the inputStream of the send method. What you did in the server code is that you are expecting to recieve String before the Long which in reserved on what you did in your send method.
solution:
switch reading long first then string
sample:
//read file size
long fileSize = 0;
try
{
fileSize = dataInputStream.readLong();
}
catch (Exception e)
{
e.printStackTrace();
}
Log.i("File Size", "" + fileSize);
//read file name
String fileName = "";
try
{
fileName = dataInputStream.readUTF();
}
catch (Exception e)
{
e.printStackTrace();
}
Log.i("File Name", "" + fileName);
I'm a newbie in android development and encounter this problem my client wish to stream video files from his camera storage to his android phone using only LAN connection.. is this possible? for now the only thing that i can do is play a video from the storage of the phone and stream http or RTSP streams video but is it possible to stream a video file while sending it through LAN? thank you.
#Androider-I apologize for not commenting because i can't anyway this is my code for now and any kind of help will be appreciated thank you.
Edited:
Client Side
`
public class Client extends Activi
ty {
private Socket client;
private FileInputStream fileInputStream;
private BufferedInputStream bufferedInputStream;
private OutputStream outputStream;
private Button button;
private TextView text;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button = (Button) findViewById(R.id.button1);
text = (TextView) findViewById(R.id.textView1);
//Button press event listener
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
File file = new File("/storage/emulated/BaseAhri.jpg");
try {
client = new Socket("10.0.2.2", 4444);
byte[] mybytearray = new byte[(int) file.length()];
fileInputStream = new FileInputStream(file);
bufferedInputStream = new BufferedInputStream(fileInputStream);
bufferedInputStream.read(mybytearray, 0, mybytearray.length);
outputStream = client.getOutputStream();
outputStream.write(mybytearray, 0, mybytearray.length);
outputStream.flush();
bufferedInputStream.close();
outputStream.close();
client.close();
text.setText("File Sent");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Server Side
private static ServerSocket serverSocket;
private static Socket clientSocket;
private static InputStream inputStream;
private static FileOutputStream fileOutputStream;
private static BufferedOutputStream bufferedOutputStream;
private static int filesize = 10000000;
private static int bytesRead;
private static int current = 0;
public static void main(String[] args) throws IOException {
serverSocket = new ServerSocket(4444);
System.out.println("Server started. Listening to the port 4444");
clientSocket = serverSocket.accept();
byte[] mybytearray = new byte[filesize];
inputStream = clientSocket.getInputStream();
fileOutputStream = new FileOutputStream("/sdcard/DCIM/Camera/BaseAhri.jpg");
bufferedOutputStream = new BufferedOutputStream(fileOutputStream);});
System.out.println("Receiving...");
bytesRead = inputStream.read(mybytearray, 0, mybytearray.length);
current = bytesRead;
do {
bytesRead = inputStream.read(mybytearray, current, (mybytearray.length - current));
if (bytesRead >= 0) {
current += bytesRead;
}
} while (bytesRead > -1);
bufferedOutputStream.write(mybytearray, 0, current);
bufferedOutputStream.flush();
bufferedOutputStream.close();
inputStream.close();
clientSocket.close();
serverSocket.close();
System.out.println("Sever recieved the file");
}
Error Server Side
[2014-01-22 15:20:15 - AndroidSocketSERVER] ActivityManager: Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.javacodegeeks.android.androidsocketserver/.Server }
[2014-01-22 15:20:15 - AndroidSocketSERVER] ActivityManager: Error type 3
[2014-01-22 15:20:15 - AndroidSocketSERVER] ActivityManager: Error: Activity class {com.javacodegeeks.android.androidsocketserver/com.javacodegeeks.android.androidsocketserver.Server} does not exist.
And in the client side it crashes after i send.not sure if this is an error since my server have a problem....
#Androider -Sorry for late update,Here is my resulting code where i am now able to pass the video file and control it by bits but the problem is my data are always corrupted because of a missing byte or something like that and now how do i stream it? i am not able to play the file because it is not complete? if that's the case then what is the purpose of byte controll? i hope you can help me again thx.
COde Client and Server:
serverTransmitButton = (Button) findViewById(R.id.button_TCP_server);
serverTransmitButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.i("Start Server Button Clicked", "yipee");
try {
// create socket
// TODO: the port should match the one in Client
ServerSocket servsock = new ServerSocket(5005);
while (true) {
Log.i("************", "Waiting...");
Socket sock = servsock.accept(); // blocks until connection opened
Log.i("************", "Accepted connection : " + sock);
// sendfile
// TODO: put the source of the file
int filesize=8192;
File myFile = new File ("/sdcard/DCIM/Camera/test.mp4");
byte [] mybytearray = new byte [filesize];
Log.i("####### file length = ", String.valueOf(myFile.length()) );
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
OutputStream os = sock.getOutputStream();
Log.i("************", "Sending...");
int read;
while((read = fis.read(mybytearray)) != -1){
os.write(mybytearray,0,read);
}
os.flush();
os.close();
fis.close();
bis.close();
}
} catch (IOException e) {
Log.i("Io execption ", "e: " + e);
}
Log.i("=============== the end of start ==============", "==");
}
});
clientReceiveButton = (Button) findViewById(R.id.button_TCP_client);
clientReceiveButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.i("Read Button Clicked", "yipee");
try {
int bufferSize;// filesize temporary hardcoded
long start = System.currentTimeMillis();
int bytesRead;
int current;
// localhost for testing
// TODO: server's IP address. Socket should match one above in server
Socket sock = new Socket("192.168.123.186",5005);
Log.i("************", "Connecting...");
// receive file
bufferSize=sock.getReceiveBufferSize();
byte [] mybytearray = new byte [bufferSize];
InputStream is = sock.getInputStream();
FileOutputStream fos = new FileOutputStream("/storage/emulated/0/testinggo.mp4");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray,0,mybytearray.length);
while((current = is.read(mybytearray)) >0){
bos.write(mybytearray, 0 , current);
}
bos.flush();
bos.close();
is.close();
sock.close
} catch ( UnknownHostException e ) {
Log.i("******* :( ", "UnknownHostException");
} catch (IOException e){
Log.i("Read has IOException", "e: " + e);
}
Log.i("=============== the end of read ===============", "==");
}
});
}
}
Actually it is. You will need to build your own socket server in app and play video from it. Then you will have control over byte input stream and save dowloaded part to file while same part will go to mediaplayer
client sends the file to server and server receives it and saves it. But when in the Client that Line(while ((len = outputFromServer.read(buf)) != -1)) comes the client stuckes i dont know why?
try {
Log.d(WiFiDirectActivity.TAG, "Opening client socket - ");
socket.connect((new InetSocketAddress(host, port)),
SOCKET_TIMEOUT);
final File f = new File(
Environment.getExternalStorageDirectory()
+ "/wifip2pshared-"
+ System.currentTimeMillis() + ".jpg");
File dirs = new File(f.getParent());
if (!dirs.exists())
dirs.mkdirs();
f.createNewFile();
// send Data To Server
OutputStream stream = socket.getOutputStream();
FileInputStream file = new FileInputStream(
"/sdcard/samsung/Image/001" + ".jpg");
while ((len1 = file.read(buf1)) != -1) {
stream.write(buf1, 0, len1);
}
file.close();
// ////////////////////////////////
// ///////////////////////
// read Data from server
InputStream outputFromServer = socket.getInputStream();
FileOutputStream saveData = new FileOutputStream(
f);
while ((len = outputFromServer.read(buf)) != -1) {
saveData.write(buf, 0, len);
}
saveData.close();
Log.d(WiFiDirectActivity.TAG, "Client: Data written");
} catch (IOException e) {
Log.e("exception at client", e.getMessage());
} finally {
if (socket != null) {
if (socket.isConnected()) {
try {
socket.close();
} catch (Exception e) {
// Give up
Log.e("exception at clientin socket close",
e.toString());
}
}
}
}
Server Side
try {
server = new ServerSocket(8988);
Socket client = server.accept();
final File f = new File(
Environment.getExternalStorageDirectory()
+ "/wifip2pshared-"
+ System.currentTimeMillis() + ".jpg");
File dirs = new File(f.getParent());
if (!dirs.exists())
dirs.mkdirs();
f.createNewFile();
// receive Data From Client
InputStream is = client.getInputStream();
FileOutputStream fos = new FileOutputStream(f);
String a = "acb";
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
Log.e("In server reviving data", a);
}
fos.close();
// Send Data To Client
OutputStream stream = client.getOutputStream();
FileInputStream file = new FileInputStream(
"/sdcard/samsung/Image/001" + ".jpg");
while ((len1 = file.read(buf1)) != -1) {
stream.write(buf1, 0, len1);
}
file.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
client sends the file to server and server receives it and saves it. But when in the Client that Line(while ((len = outputFromServer.read(buf)) != -1)) comes the client stuckes i dont know why?
read() on a socket stream will return -1 only if connection is closed or an error occurs. Server receives the data and saves it but never leaves the receiver loop to send data. Even if it would do the client wouldn't then leave its receiver loop either.
You must either close the connection or send file size before the actual file and receiving stops when given size was read.