二进制数据与GWT

二进制数据与GWT,gwt,binary,bytearray,Gwt,Binary,Bytearray,关于二进制数据和GWT已经有几个问题了。在阅读了它们之后,我仍然不确定以下内容是否可行(尽管我是一个完全的GWT初学者!) 我有一些非常复杂的数据文件,它们只以二进制形式存在,我无法将它们转换为XML或JSON之类的格式。我有一个封闭的源代码库,它接受字节[],并返回一个我可以使用的Java对象。为了让我的GWT应用程序运行,我“打印”了其中一个二进制数据文件,并将生成的字节[]硬编码到一个.java文件中,我可以从GWT应用程序代码访问该文件。一切正常。显然,这只是一个测试,在部署的应用程序中

关于二进制数据和GWT已经有几个问题了。在阅读了它们之后,我仍然不确定以下内容是否可行(尽管我是一个完全的GWT初学者!)

我有一些非常复杂的数据文件,它们只以二进制形式存在,我无法将它们转换为XML或JSON之类的格式。我有一个封闭的源代码库,它接受字节[],并返回一个我可以使用的Java对象。为了让我的GWT应用程序运行,我“打印”了其中一个二进制数据文件,并将生成的字节[]硬编码到一个.java文件中,我可以从GWT应用程序代码访问该文件。一切正常。显然,这只是一个测试,在部署的应用程序中,我无法硬编码这些数据文件。我想将它们放在我的GWT应用程序所在的目录中,并用我的GWT应用程序“加载”它们

我想我可以用GWT从服务器“加载”文本文件,对吗?为什么我不能用GWT读取二进制数据?或者我可以将二进制数据文件读取为文本,并将字符串读入字节[]?我读了很多关于base64编码的书,GWT也能读懂,尽管我不太明白他们在说什么。我可以将服务器配置为以base64编码的方式提供这些二进制数据文件,然后用GWT读取它们吗

还是有其他解决办法?如果我能帮忙的话,我不想碰任何JS代码。这就是为什么我开始使用GWT;)

谢谢你的帮助:)

是的,这是可能的

两种解决方案取决于数据类型

  • 动态(如果二进制数据是动态的并且可能会更改):
    只需在后端对二进制数据进行Base64编码并提供服务(即GET请求)。 然后,您可以使用GWT的任何通信协议(有关更多详细信息,请参阅)从后端检索数据。
    然后,您必须对数据进行base64解码并使用它(正如您已经解决的那样)

  • 静态(如果二进制数据不会更改并且在编译时已知):
    您可以使用(即:DataResource)在编译时生成这些二进制文件,然后在客户端自动检索它们,而无需手动设置传输它们

  • 客户端:

    @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;
    }
    
    @覆盖
    moduleload()上的公共void
    {
    RequestBuilder rb=newrequestbuilder(RequestBuilder.GET,“/test”);
    尝试
    {
    rb.sendRequest(null,newrequestcallback()
    {
    @凌驾
    接收到公共无效onResponseReceived(请求-请求,响应-响应)
    {
    字符串编码=response.getText();
    字节[]数据=解码(编码);
    System.out.println(Arrays.toString(data));
    }
    @凌驾
    公共void onError(请求,可丢弃异常)
    {
    }
    });
    }
    捕获(请求异常e)
    {
    e、 printStackTrace();
    }
    }
    私有最终静态字符串base64chars=“abcdefghijklmnopqrstuvwxyzabefghijklmnopqrstuvwxyz012456789+/”;
    公共静态字节[]解码(字符串s)
    {
    //删除/忽略任何不在base64字符列表中的字符
    //或者pad字符,尤其是换行符
    s=s.replaceAll(“[^”+base64chars+”=],”);
    //将任何传入的填充替换为零填充(a字符为
    //零)
    字符串p=(s.charAt(s.length()-1)='='?(s.charAt(s.length()-2)='='='?“AA:“A”):“”);
    s=s子串(0,s.length()-p.length())+p;
    int resLength=(int)Math.ceil(((s.length())/4f)*3f);
    字节[]bufIn=新字节[resLength];
    int bufIn_i=0;
    //此加密字符串长度的增量,四个字符
    //一次
    对于(int c=0;c>>8)和0xFF);
    字符c3=(字符)(n&0xFF);
    bufIn[bufIn_i++]=(字节)c1;
    bufIn[bufIn_i++]=(字节)c2;
    bufIn[bufIn_i++]=(字节)c3;
    }
    byte[]out=新字节[bufIn.length-p.length()];
    System.arraycopy(bufIn,0,out,0,out.length);
    返回;
    }
    
    服务器端(Java):

    @覆盖
    public void doGet(HttpServletRequest请求,HttpServletResponse响应)抛出ServletException,IOException
    {
    字节[]二进制数据=新字节[1000];
    对于(int i=0;i<1000;i++)
    二进制数据[i]=(字节)(byte.MIN_值+(i%(Math.pow(2,byte.SIZE)));
    System.out.println(“发送:”+Arrays.toString(binaryData));
    字节[]base64Encoded=org.apache.commons.codec.binary.Base64.encodeBase64(二进制数据);
    setContentType(“应用程序/八位字节流”);
    PrintWriter out=response.getWriter();
    write(新字符串(base64Encoded));
    }
    
    让我们假设我们使用的是HTML4

    GWT客户端无法“读取”文件。GWT客户端是在浏览器上运行的javascript。浏览器安全性不允许您读取本地文件。您必须让servlet代理读取服务器上的文件

    设置文件的mime类型是因为您希望浏览器下载文件并调用本地PC来调用相应的软件,例如,pdf来调用pdf reader或xls来调用ms excel。与GWT Java或Javascript无关(启用下载除外)

    为什么需要GWT客户端读取二进制文件?如果您这样做,您的架构可能是错误的。“错”是一个不友善的词。也许,“未对齐”是一个更好的词。您对AJAX瘦客户机服务器的概念不一致。当你进入GWT之门时,把你的桌面处理概念和习惯放在门口

    GWT是Java,但不是Java

    我一直在提醒人们,GWT Java只是Javascript的一种更连贯的表示形式。当您使用GWT Java编写代码时,alwa
    @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));
    }
    
            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();