Загрузка двоичного файла с использованием сокетного соединения в Java ME - PullRequest
2 голосов
/ 25 марта 2012

Я пытаюсь загрузить файл pdf на свой мобильный телефон (используя Java ME), используя SocketConnection Api. Идея состоит в том, чтобы отправить серверу запрос HTTP GET, и он ответит данными с файлом PDF. Однако проблема, с которой я сталкиваюсь, заключается в том, что сервер сначала отвечает обратно строковыми данными (HTTP Headers), а затем двоичными данными. Я просто хочу хранить двоичные данные (файл PDF).

Я написал этот код до сих пор, и он отлично работает, если сервер отвечает с помощью строковых данных. Однако, когда он отвечает обратно с двоичными данными, этот код все еще пытается сохранить все как строку, правильно сохраняя первоначально возвращенные HTTP Headers (не обязательные) и затем искаженные биты, соответствующие двоичным данным моего файла PDF.

public void FileDownload() {
    try {
        sc = (SocketConnection) Connector.open("socket://" + hostname + ":" + port);
        OutputStream os = sc.openOutputStream();
        os.write(("GET " + link_to_file_to_be_downloaded + " HTTP/1.0\r\n").getBytes("UTF-8"));
        os.write(("HOST: " + hostname + "\r\n").getBytes("UTF-8"));
        os.write(("\r\n").getBytes("UTF-8"));
        os.flush();
        os.close();

        String url = "file:///E:/Data/" + "binary_data.pdf";
        FileConnection fconn = (FileConnection) Connector.open(url, Connector.READ_WRITE);
        if (!fconn.exists()) {
            fconn.create();
        }
        OutputStream ops = fconn.openOutputStream();
        byte data = 0;
        in = sc.openInputStream();
        data = (byte) in.read();
        while (data != -1) {
            ops.write(data);
            data = (byte) in.read();
        }
        ops.flush();
        ops.close();
        fconn.close();                

    } catch (IOException ex) {
        parent_class.main_form.append("Exception occured while "
                + "downloading file: " + ex.toString() + "\n");
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (IOException ex) {
                parent_class.main_form.append("Exception occured while "
                        + "downloading file: " + ex.toString() + "\n");
            }
        }
    }
}

Это то, что хранится в файле "binary_data.pdf" с использованием этого кода -

HTTP/1.1 200 OK
Date: Sun, 25 Mar 2012 07:03:10 GMT
Server: Apache/2.2.14 (Ubuntu)
Last-Modified: Tue, 20 Mar 2012 22:00:45 GMT
ETag: "420050-12bad-4bbb3ce85fd21"
Accept-Ranges: bytes
Content-Length: 76717
Content-Type: application/pdf
Via: 1.0 www.XXX.XXX.org
Connection: close

%PDF-1.4
%????
3 0 obj <<
/Length 4077      
/Filter /FlateDecode
>>
stream
x??ZYs?6~????9U.?#??Udg?M*qYJ???T-4?fq? @Z????<FT?}
lt7??n???_???4?s???????"
3????<???^?V?z??M?z??m?^????V???o??S'm6?????.??/Sx??Y?av?MB?*b^?f??/?IO??B??q??/?(??aT?a?@#??,?%???Z8? ?]??-?\?]??????nw?2?;?????Z?;?[}??????&J=ml??-??V?|??:??"?(?Gf??D??~?QW?U?Z???cP?b???QX

(Эта операция может быть проще при использовании верхнего уровня HttpConnection API, но я хочу понять, как все работает на самом базовом уровне, и поэтому вместо этого я использую SocketConnection API.)

Короче говоря, я хочу, чтобы мое приложение просто интерпретировало данные, отвечаемые сервером правильно, как строковые или двоичные, и затем соответственно сохраняло двоичный файл (возможно, отбрасывая строковые заголовки HTTP).

Ответы [ 2 ]

4 голосов
/ 26 марта 2012

Я нашел решение. Ниже приведен рабочий код.
Сначала я храню заголовок ответа в виде строки. Заголовки заканчиваются на \r\n\r\n, (поэтому читайте в байтах до этих символов). Позже я храню (возможно) двоичные данные в файле отдельно.

    public String FileDownloadNonPersistently() {
        String server_reply = new String();
        try {
            sc = (SocketConnection) Connector.open("socket://" + hostname + ":" + port);
            os = sc.openOutputStream();
            os.write(("GET " + link_to_file_to_be_downloaded + 
                    " HTTP/1.0\r\n").getBytes("UTF-8"));
            os.write(("HOST: " + hostname + "\r\n").getBytes("UTF-8"));
            os.write(("\r\n").getBytes("UTF-8"));
            os.flush();
            os.close();

            in = sc.openInputStream();
            // 1. Read the response header from server separately beforehand.
            byte data;
            String temp_char = "";
            while (!"\r\n\r\n".equals(temp_char)) {
                data = (byte) in.read();
                server_reply += String.valueOf((char) data);
                if (((char) data) == '\r' || ((char) data) == '\n') {
                    temp_char += String.valueOf((char) data);
                } else {
                    temp_char = "";
                }
            }

            // 2. Recieving the actual data, be it text or binary
            current = 0;
            mybytearray  = new byte[filesize];
            bytesRead = in.read(mybytearray,0,mybytearray.length);
            current = bytesRead;
            do {
                bytesRead = in.read(mybytearray, current,
                       (mybytearray.length-current));
                if(bytesRead >= 0) current += bytesRead;
            } while(bytesRead > -1);

            // Store recieved data to file, if set true from options
            if (tcp_save_downloaded_file == true) {
                // decide an appropriate file name acc. to download link
                String url = "file:///E:/Data/" + "tcp_downloaded_file.pdf";
                FileConnection fconn = (FileConnection) 
                        Connector.open(url, Connector.READ_WRITE);
                if (!fconn.exists()) {      // XXX. what if file already present? overwrite or append mode?
                    fconn.create();
                }
                OutputStream ops = fconn.openOutputStream();
                ops.write(mybytearray, 0 , current);
                ops.flush();
                ops.close();
            }

        } catch (Exception ex) {
            parent_class.main_form.append("Exception occured while "
                    + "downloading file: " + ex.toString() + "\n\n");
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ex) {
                    parent_class.main_form.append("Exception occured while "
                            + "closing inputstream "
                            + "after downloading file: " + ex.toString() + "\n\n");
                }
            }
            // XXX. see if you need to close the OutputStreams and 
            // SocketConnection as well.
            return server_reply;
        }
    }
0 голосов
/ 26 марта 2012

Первые 10 строк являются заголовками сообщений HTTP. Для получения дополнительной информации о них, пожалуйста, перейдите на http://tools.ietf.org/html/rfc2616#page-31.

Пустая строка указывает, где начинается тело.

Вы можете начать сохранение содержимого PDF со строки 12 и далее, но вы должны сделать это, используя другой метод чтения. Вместо


    data = (byte) in.read();
    while (data != -1) {
        ops.write(data);
        data = (byte) in.read();
    }

пожалуйста, попробуйте


    byte buff[] = new byte[1024];
    int len = in.read(buff);
    while (len > 0) {
        ops.write(buff, 0, len);
        len = in.read(buff);
    }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...