簡體   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