2

バイナリ データと GWT については、すでにいくつかの質問があります。それらを読んだ後、次のことが可能かどうかはまだわかりません(ただし、私は完全なGWT初心者です!):

バイナリ形式でしか存在しない非常に複雑なデータファイルがいくつかあり、それらを XML や JSON などに変換できません。私はバイト[]を受け入れ、使用できるJavaオブジェクトを返すクローズドソースライブラリを持っています。GWT アプリを実行するために、これらのバイナリ データ ファイルの 1 つを「印刷」し、GWT アプリ コードからアクセスする .java ファイルに結果の byte[] をハードコーディングしました。すべて正常に動作します。明らかに、これは単なるテストであり、展開されたアプリでは、これらのデータ ファイルをハードコーディングすることはできません。それらをGWTアプリが存在するディレクトリに配置し、GWTアプリでそれらを「ロード」したいと思います。

GWTを使用してサーバーからテキストファイルを「ロード」できると思いますよね?GWT でバイナリ データを読み取れないのはなぜですか? または、バイナリ データ ファイルをテキストとして読み取り、文字列をバイト [] に読み取ることはできますか? 私はbase64エンコーディングについて多くのことを読んでおり、GWTはそれを読み取ることができますが、彼らが何について話しているのかはよくわかりません. これらのバイナリ データ ファイルを base64 エンコードとして提供し、GWT で読み取るようにサーバーを構成できますか?

または、他の解決策はありますか?できればJSコードには触れたくありません。それが私がGWTを使い始めた理由です;)

ご協力いただきありがとうございます :)

4

4 に答える 4

5

HTML 4 を使用していると仮定しましょう。

GWT クライアントはファイルを「読み取る」ことができません。GWT クライアントは、ブラウザ上で実行される JavaScript です。ブラウザのセキュリティでは、ローカル ファイルを読み取ることはできません。サーバー上のファイルをプロキシ読み取りするサーブレットを取得する必要があります。

ファイルの MIME タイプを設定するのは、ブラウザでファイルをダウンロードし、ローカル PC を起動して適切なソフトウェアを起動するためです。たとえば、pdf リーダーを起動するには pdf を、Excel を起動するには xls を起動します。GWT Java または Javascript とは何の関係もありません (ダウンロードを有効にすることを除いて)。

バイナリ ファイルを読み取るために GWT クライアントが必要なのはなぜですか? もしそうなら、あなたのアーキテクチャはおそらく間違っています。「間違っている」は不親切な言葉です。おそらく、ミスアラインメントはより良い言葉です。AJAX シン クライアント サーバーの概念がずれています。GWT のドアに入ったら、デスクトップ処理の概念と習慣をドアに落としてください。

GWT は Java ですが、Java ではありません

私は、GWT Java は Javascript のより一貫した表現にすぎないことを人々に思い出させなければなりません。GWT Java でコーディングするときは、実際には Java ではなく Javascript でコーディングしていることを常に覚えておいてください。すべての Java ソースは Javascript に変換されます

したがって、GWT コンパイラーは、すべての Java クラスをソース・コードで提供する必要があります。GWT コンパイラには、Java バイトコードの jar/class ファイルを Javascript に変換する機能がありません。ライブラリがバイトコードの場合、またはソース ライブラリが呼び出しチェーンのどこかでバイトコード ライブラリを呼び出す場合、コンパイルは失敗します。

サーバー側とクライアント側の GWT の混乱

GWT RPC は、GWT 初心者にとって混乱の元になることがあります。彼らは、リモート サーブレットがサーバー上で実行されているため、バイトコードにコンパイルされる唯一の部分であることを認識していないようです。特に、Vaadin を使用している場合は、サーバーとブラウザーの間の境界線が意図的にぼやけているためです。そのため、GWT の初心者は、「なぜ私のバイトコード ライブラリはアプリの特定の部分でしか機能しないのか?」と疑問に思います。

ajax クライアント サーバー アーキテクチャ

GWT は単なる Web 対応 UI です。サーバー上でやりたいことを何でも実行できず、サーバーが実行していること、または実行したことを UI に反映させることができないのはなぜですか? なぜブラウザで行う必要があるのですか?

GWT インターフェースが強化された JSP であると想像してみてください。JSP を作成しているとします。JSP にバイナリ データをブラウザに吸い込ませ、JSP に Javascript を生成させてそこでバイナリ データを分析させますか?

私は複雑な統計分析を書いてきましたが、サーバー上で行われていることを反映するためにブラウザーを使用しただけです。エンジニアは、自分の PC で解析を実行していると考えています。チャート/レポートが生成されます。しかし、SAS を呼び出すことによって、すべてサーバー上で行われます。

サービス指向のパターン/アーキテクチャ

サーバーがサービスを提供します。ブラウザ GWT クライアントは、これらのサービスを要求します。ファイルを開き、ファイルを読み取り、ファイルを分析し、分析のビジュアル/MIME 表現を生成してブラウザに渡します。GWT ブラウザー クライアントは、サーバー ベースの操作用のディスプレイ モニターと考えてください。GWT は、エンジニアがローカル PC で分析を行っているように錯覚させる魔法のようなトリックです。もちろん、エンジニアである彼らのほとんどは、ブラウザーが実際に作業を行っていないことを知っています。

ユーザーが分析に満足したら、結果の MIME 表現を生成するサービスを取得します。これにより、MIME によってマップされた適切なローカル PC ソフトウェアを呼び出すためにブラウザーによってダウンロードされます。

サーバー上で行い、ブラウザに反映します。

さらに編集:バイナリデータについて...

Web アプリで使用される base64 エンコーディングの背後にある動機: 認証トークン、画像、音声ファイルの送信 - それらのバイナリ表現とシーケンスがエンディアンなどのアーキテクチャ上のニュアンスによって台無しにされないようにします。

たとえば、未加工のバイナリ スプレッドシートを読み取るブラウザ アプリを作成しようとしないでください。ブラウザ アプリに送信する前に、バイナリ要素を base64 でエンコードする必要がある XML または JSON (できれば JSON) にサーバーに変換させます。または、あなたの人生の目的がエベレストに登ることである場合は、base64 の代わりにアーキテクチャにとらわれないエンコーディングを発明して、バイナリ データを送信します。

ブラウザの OS 処理 (音声、画像、PDF など) の場合は、バイナリ情報のみを使用してください。JavaScript ルーチンだけで処理するバイナリ データを送信しても意味がありません。JavaScriptルーチンは、それを翻訳するために余分な処理時間を使用する必要があります(繰り返しますが、あなたの人生の目的が登ることである場合を除きます... )。

于 2012-06-19T07:35:31.733 に答える
4

クライアント側:

@Override
public void onModuleLoad()
{
    RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, "/test");
    try
    {
        rb.sendRequest(null, new RequestCallback()
        {
            @Override
            public void onResponseReceived( Request request, Response response )
            {
                String encoded = response.getText();
                byte[] data = decode(encoded);
                System.out.println(Arrays.toString(data));
            }

            @Override
            public void onError( Request request, Throwable exception )
            {
            }
        });
    }
    catch( RequestException e )
    {
        e.printStackTrace();
    }
}

private final static String base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

public static byte[] decode( String s )
{

    // remove/ignore any characters not in the base64 characters list
    // or the pad character -- particularly newlines
    s = s.replaceAll("[^" + base64chars + "=]", "");

    // replace any incoming padding with a zero pad (the 'A' character is
    // zero)
    String p = (s.charAt(s.length() - 1) == '=' ? (s.charAt(s.length() - 2) == '=' ? "AA" : "A") : "");
    s = s.substring(0, s.length() - p.length()) + p;
    int resLength = (int) Math.ceil(((s.length()) / 4f) * 3f);
    byte[] bufIn = new byte[resLength];
    int bufIn_i = 0;

    // increment over the length of this encrypted string, four characters
    // at a time
    for( int c = 0; c < s.length(); c += 4 )
    {

        // each of these four characters represents a 6-bit index in the
        // base64 characters list which, when concatenated, will give the
        // 24-bit number for the original 3 characters
        int n = (base64chars.indexOf(s.charAt(c)) << 18) + (base64chars.indexOf(s.charAt(c + 1)) << 12)
                + (base64chars.indexOf(s.charAt(c + 2)) << 6) + base64chars.indexOf(s.charAt(c + 3));

        // split the 24-bit number into the original three 8-bit (ASCII)
        // characters
        char c1 = (char) ((n >>> 16) & 0xFF);
        char c2 = (char) ((n >>> 8) & 0xFF);
        char c3 = (char) (n & 0xFF);

        bufIn[bufIn_i++] = (byte) c1;
        bufIn[bufIn_i++] = (byte) c2;
        bufIn[bufIn_i++] = (byte) c3;
    }

    byte[] out = new byte[bufIn.length - p.length()];
    System.arraycopy(bufIn, 0, out, 0, out.length);
    return out;
}

サーバー側 (Java):

@Override
public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException
{
    byte[] binaryData = new byte[1000];
    for( int i = 0; i < 1000; i++ )
        binaryData[i] = (byte) (Byte.MIN_VALUE + (i % (Math.pow(2, Byte.SIZE))));
    System.out.println("Sending: " + Arrays.toString(binaryData));

    byte[] base64Encoded = org.apache.commons.codec.binary.Base64.encodeBase64(binaryData);

    response.setContentType("application/octet-stream");
    PrintWriter out = response.getWriter();
    out.write(new String(base64Encoded));
}
于 2012-06-16T01:40:29.663 に答える
4

はい、可能です。

データの種類に応じて 2 つのソリューション。

  1. 動的(バイナリ データが動的で、変更される可能性がある場合):
    バックエンドでバイナリ データを Base64 エンコードして提供します (つまり、GET 要求)。その後、GWT の通信プロトコル (詳細についてはこちらを参照) のいずれかを使用して、バックエンドからデータを取得できます。
    次に、データをbase64でデコードして操作する必要があります(すでに解決しているため)。

  2. 静的(バイナリ データが変更されず、コンパイル時に既知である場合): ClientBundle
    (つまり、DataResource) を 使用して、コンパイル時にこれらのバイナリ ファイルを生成し、手動で設定しなくてもクライアント側で自動的に取得できます。それらを転送します。

于 2012-06-15T13:38:13.220 に答える
1

任意の URL からバイトを簡単に読み取ることができるソリューションを次に示します。

        XMLHttpRequest request = XMLHttpRequest.create();
        request.open("GET", "http://127.0.0.1:8888/sample/index.bin");
        request.setResponseType(ResponseType.ArrayBuffer);
        request.setOnReadyStateChange(new ReadyStateChangeHandler() {

            @Override
            public void onReadyStateChange(XMLHttpRequest xhr) {
                if (xhr.getReadyState() == XMLHttpRequest.DONE) {
                    if (xhr.getStatus() == 200) {
                        ArrayBuffer buffer = xhr.getResponseArrayBuffer();
                        Uint8Array array = TypedArrays.createUint8Array(buffer);
                        System.out.println("got " + array.length() + " bytes: ");
                        for (int i = 0; i < array.length(); i++) {
                            System.out.println(array.get(i));
                        }
                    } else {
                        System.out.println("response status: " + xhr.getStatus() + " " + xhr.getStatusText());
                    }
                }
            }
        });
        request.send();
于 2015-04-16T22:22:14.257 に答える