繁体   English   中英

通过Java套接字将文件发送到Android设备时数据丢失

[英]Data loss when sending file via java socket to an Android device

我用Java开发了一个基于套接字的聊天应用程序。 我在Android上创建了两个客户端,即桌面客户端和移动客户端,现在添加了文件发送功能,一切都很好,现在我添加了文件发送功能,在Android客户端上我面临不确定的行为,有时它会获取整个文件,有时会读取文件时崩溃,或者我使用与桌面客户端完全相同的传输代码! 我的客户端应用程序以json格式向服务器发送命令,服务器以与结果相同的格式进行回复,在文件请求中,服务器回复中包含“ files”文件,因此客户端应输入MFtp.ftpGetFile方法,因为服务器将带有file的结果发送为字段后,自动在sendFile方法中输入这是我的传输代码!

MFtp.java

package com.molo.ftp;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class MFtp {
public static boolean ftpPut(File file,DataOutputStream out){
    //File file=new File(fname);
    if(!file.exists())
        return false;
    {
        System.out.println("Begin sending file");
        BufferedInputStream fin=null;
        try{
            fin= new BufferedInputStream(new FileInputStream(file));
            String fname=file.getName();
            long fileSize=file.length();
            //send file name;
            out.writeUTF(fname);
            //send file size
            out.writeLong(fileSize);
            out.flush();//send completely those informations
            int byteRead=0;
            byte[] buffer=new byte[(int) Math.min(4096, fileSize)];
            System.out.println("Buffer size: "+buffer.length);
            while((byteRead=fin.read(buffer))>0){
                out.write(buffer,0,byteRead);
                out.flush();
                System.out.println("BYTE READ AND WRITE TO SERVER :"+byteRead);
            }
            System.out.println("File totaly sent");
            out.flush();
            fin.close();
        }catch(NumberFormatException e){
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
    return true;
}
 public static boolean ftpPut(String fname,DataOutputStream out){
    File file=new File(fname);
    if(!file.exists())
        return false;
     {
        System.out.println("Begin sending file");
        BufferedInputStream fin=null;
        try{
            fin= new BufferedInputStream(new FileInputStream(file));
            long fileSize=file.length();
            fname=file.getName();
            //send file name;
            out.writeUTF(fname);
            //send file size
            out.writeLong(fileSize);
            out.flush();//send completely those informations
            int byteRead=0;
            byte[] buffer=new byte[(int) Math.min(4096, fileSize)];
            System.out.println("Buffer size: "+buffer.length);
            while((byteRead=fin.read(buffer))>0){
                out.write(buffer,0,byteRead);
                out.flush();
                System.out.println("BYTE READ AND WRITE TO SERVER :"+byteRead);
            }
            System.out.println("File totaly sent");
            out.flush();
            fin.close();
        }catch(NumberFormatException e){
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
    return true;
}
public static File ftpGetFile(DataInputStream din,String dir){

    //read file size from the client
    try{
        //read file name
        String fname=din.readUTF();
        //read filename
        long fileSize=din.readLong();

        File outPut=new File(dir+"/"+fname);
        BufferedOutputStream fout=null;
        fout= new BufferedOutputStream(new FileOutputStream(outPut));
        long byteRestants=fileSize;
        byte[] buffer=new byte[(int) Math.min(4096, fileSize)];
        System.out.println("Start receiving file: "+fname+" / "+fileSize);
        int byteToRead=0;
        while(byteRestants>0){
            byteToRead=din.read(buffer, 0,(int)Math.min(buffer.length, byteRestants));
            byteRestants-=byteToRead;
            fout.write(buffer,0,byteToRead);
            System.out.println("Byte restant: "+byteRestants);
        }
        fout.close();
        return outPut;
    }catch(NumberFormatException e){
        return null;
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return null;
    }   
}

}

而更高的是我的客户端读取线程代码,在这里我调用MFtp getFile方法:

private class ReadThread extends Thread{
    @Override
    public void run() {
        if(reader==null){
            try {
                System.out.println("Openning");
                reader=new DataInputStream(new BufferedInputStream(socket.getInputStream()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        while(go){

            try {
                String line= readLine(reader);
                if(line==null)
                    break;
                System.out.println("Client.ReadThread:line "+line);
                JSONObject result= new JSONObject(line);
                if(!result.has("hash"))
                    continue;
                Response r=new Response(result.getLong("hash"),result.getInt("status"), result.get("data"));
                //System.out.println("Result: "+result.toString());
                MediaFile[] medias=null;
                if(result.has("files")){
                    JSONArray list=result.getJSONArray("files");
                    System.out.println("Client.ReadThread:line "+"Has Media :"+list.length());
                    // List<MediaFile> files= new ArrayList<>();
                    medias=new MediaFile[list.length()];
                    for(int i =0;i<list.length();i++){
                        JSONObject obj=list.getJSONObject(i);
                        MediaFile m=new MediaFile();
                        m.name=obj.getString("name");
                        m.size=obj.getLong("size");
                        m.type=obj.getString("type");
                        Log.e("Client.medias.receiving","m.size: "+m.size+" m.name "+m.name+" m.type : "+m.type);
                        m.file= MFtp.ftpGetFile(reader, MainActivity.TEMP_DIR);
                        if(m.file!=null){
                            m.absolutPath=m.file.getAbsolutePath();
                            Log.e("Client.received: ",m.absolutPath);
                        }else{
                            Log.e("Client.received: ","Failed to save file");
                            System.out.println("Client.received: "+"Failed to save file");
                        }
                    }
                }
                r.medias=medias;
                if(queryManager!=null && r.hash>0){
                    queryManager.onResult(r);
                }
                else if(listener!=null && r.hash<=0)
                    listener.onReceiveNewMessage(r);
            }catch(SocketException e){
                if(listener!=null)
                    listener.onSocketExceptionWhenRead(socket);
            }
            catch (IOException e) {
                if(listener!=null)
                    listener.onIOExceptionWhenRead(socket);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            try {
                Thread.sleep(40);
            } catch (InterruptedException e) {
                // TODO: handle exception
                //readThread.interrupt();
                break;
            }
        }

    }
}

阅读器线程在套接字上列出,当它从套接字接收到新消息时,将其解析为json格式,然后创建一个新的Response对象,但是如果响应包含files字段,那么这意味着servur将发送一个文件,就像代码中的hier

...............
else if(command.matches("getUserProfil")){
    if(request.has("user")){
        String userLog=request.get("user").asText();
        ObjectNode n=mapper.createObjectNode();
        Membre m=memberManager.getOne(userLog);
        MediaFile f=new MediaFile();
        f.file=new File(m.getProfil());
        f.name=f.file.getName();
        f.size=f.file.length();
        f.type="image/png";
        n.put("cache", true);
        System.out.println("SIZE: "+f.size+" ;; "+f.size);
        println(mOut, createResponse(comId, MyStandarMessageType.OK, n,f));//will send a json string with "files" as a field
        mOut.flush();
        sendFile(f);
    }
}
...........the sendFile method.........
private void sendFile(MediaFile... files) throws IOException {
    if(files!=null && files.length >0){
        System.out.println("SendFile");
        for(MediaFile f:files){
            System.out.println("Start sending file");
            MFtp.ftpPut(f.file,mOut);
        }   
    }
}

在桌面上没有问题,但是在Android客户端上,有时可以成功接收文件,但是更多次没有! 最不合理的是,在客户端读取线程中,在ftpGetFile方法中输入后,将调用String line line = readLine(reader)(在readThread中),而不是在ftpGetFile方法中使用字符串fname = din.readUTF()

在某些情况下,这是日志猫,但有时会完全接收文件

I/System.out: Client.ReadThread:line {"hash":2,"status":200,"data":{"cache":true},"files":[{"type":"image/png","size":1875,"name":"prof_molo_1492209637904.png"}]}
I/System.out: Client.ReadThread:line Has Media :1
I/System.out: Client.ReadThread:line prof_molo_1492209637904.png
I/System.out: fGetFile
I/System.out: MFt.ftpGetFile name :
I/System.out: MFt.ftpGetFile size: 122915152
W/System.err: java.io.FileNotFoundException: /storage/sdcard0/molochat/temp: open failed: EISDIR (Is a directory)
W/System.err: org.json.JSONException: Value prof_molo_1492209637904.png of type java.lang.String cannot be converted to JSONObject
W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:416)
W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:73)
W/System.err:     at com.molo.app.chat.ftp.MFtp.ftpGetFile(MFtp.java:99)
W/System.err:     at com.molo.app.chat.net.Client$ReadThread.run(Client.java:228)
W/System.err: Caused by: libcore.io.ErrnoException: open failed: EISDIR (Is a directory)
W/System.err:     at org.json.JSON.typeMismatch(JSON.java:111)
W/System.err:     at org.json.JSONObject.<init>(JSONObject.java:158)
W/System.err:     at org.json.JSONObject.<init>(JSONObject.java:171)
W/System.err:     at com.molo.app.chat.net.Client$ReadThread.run(Client.java:209)
W/System.err:     at libcore.io.Posix.open(Native Method)
W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:400)
W/System.err:   ... 4 more
E/Client.received:: Failed to save file
I/System.out: Client.received: Failed to save file

:'(

请帮助!

这是我的错误,当应用程序进入暂停状态时,我没有正确关闭线程,因此在恢复时创建了一个新的读取线程,因此未按预期处理数据!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM