【问题标题】:Transfer huge data from servlet to android application将大量数据从 servlet 传输到 android 应用程序
【发布时间】:2011-10-04 11:43:33
【问题描述】:

我正在开发一个 android 应用程序,我必须在其中将位图存储在远程服务器中。 步骤是:

步骤 1: 将位图转换为字节数组并将其从 android 应用程序发送到服务器。我将位图作为 MultipartEntity 发送。在服务器端,我在 doPost() 方法中接收它。

第二步:将字节数组存入mysql数据库。Bitmap存储为blob数据类型。我可以将接收到的字节数组存入mysql数据库。

第3步:检索存储为blob的位图并将其发送回android应用程序。我能够检索blob并转换为字节数组并发送它。

我的问题

问题是从服务器发送的数据是小批量接收的。图像长度为 1380,但以 10's、50's、100's 的可变长度接收。当我将总数加起来时,我只得到 1345,缺少一些字节数据。我在接收端发布代码。

URL url = new URL( "http://10.0.2.2:8080/ServerPartProject/BlobGetter");
 URLConnection yc = url.openConnection();              
 BufferedReader in = new BufferedReader(new       InputStreamReader(yc.getInputStream()));                                                      String data;
 int val=0; 
 while((data=in.readLine())!=null){
    val=val+data.length();  //The data.length is like 10,20..
 }
 System.out.println("Total value obtained is "+val);//val was 1345 where it should be 1380

发送结束:

OutputStreamWriter writer = new OutputStreamWriter(response.getOutputStream());
writer.write(senddata);

如何全面接收?

【问题讨论】:

    标签: java android mysql servlets blob


    【解决方案1】:

    不要使用readLine()。 您正在处理原始数据。原始数据没有只有文本才有的行。

    您的某些字节可能已转换为 2 字节 unicode 字符,这解释了您感知到的数据丢失。

    【讨论】:

    • java.io.InputStream 或 java.io.BufferedInputStream 和他们的朋友。 :-)
    • 谢谢,我使用了 InputStream,我能够一次接收全部数据,但问题是接收到的图像看起来很模糊。这是什么原因?这是否意味着数据会损坏还是压缩问题?我使用 bmp.compress(CompressFormat.JPEG,20 , bos) 压缩并发送到服务器
    • 你怎么知道它是模糊的?你如何保存/打开/显示它?
    • 是的,我只是将接收到的字节转换为位图并在 imageview 中显示。模糊的原因是从 android 应用程序发送到服务器时有几个字节被损坏。无论如何我解决了这个问题.问题是我没有使用 InputStream 将图像从 android 应用程序发送到服务器,我使用 MultiPartEntity 我相信这是导致问题的原因。谢谢 milbollma :)
    【解决方案2】:

    我会避免使用面向字符的 Reader 和 Writer 来发送和接收图像数据(大概是二进制的 [如果你是 base64 编码或其他东西,你没有提到,忽略这个])。字节被解释为字符,转换回字节,然后再次解释为字符,最后返回字节;在此过程中,图像数据被破坏。使用 Http 对象提供的 InputStream/OutputStream 接口,而不是在它们上面放置 Readers 和 Writers。

    【讨论】:

      【解决方案3】:

      您正在使用 readLine() 读取字节数据,如果不是问题的话,这至少很奇怪。在您的示例代码中,您没有关闭您的阅读器(应该是 InputStreams)。缓冲输入可能会在缓冲区中留下一些字节,这些字节在刷新或关闭之前不会被读取。

      希望这会有所帮助。

      【讨论】:

        【解决方案4】:

        您可以使用 JSON。

        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            List<String> list = new ArrayList<String>();
            list.add("item1");
            list.add("item2");
            list.add("item3");
            String json = new Gson().toJson(list);
        
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            response.getWriter().write(json);
        }
        

        这将构建并返回以下 JSON 格式的 List

        ["item1","item2","item3"]
        

        这又可以被 Android 中的org.json API 解析如下:

        String jsonString = getServletResponseAsStringSomehow(); // HttpClient?
        JSONArray jsonArray = new JSONArray(jsonString);
        List<String> list = new ArrayList<String>();
        
        for (int i = 0; i < jsonArray.length(); i++) {
            list.add(jsonArray.getString(i));
        }
        
        // Now you can use `list`.
        

        【讨论】:

          【解决方案5】:

          如果您的数据库驻留在本地而不是互联网云中,您可以使用 JDBC 连接器 mysql-connector-java-3.0.17-ga-bin.jar 通过 JDBC API 直接访问它。不是说你不能远程访问你的数据库,而是直接在云端公开你的数据库是非常不明智和冒险的。

          要在 Android 中将 blob 读取到 bmp,您可以使用 BitmapFactory,如下所示:

          // this is a snippet of course..
          
          try
          {
            Class.forName("com.mysql.jdbc.Driver");
            String astring = "jdbc:mysql://localhost:3306/mydb?user=root&password=pass"; 
            Connection ac = DriverManager. getConnection(astring);
            Statement st = ac.GetStatement();
            astring = "SELECT MYBLOB FROM MYTABLE";  // create your query here
            ResultSet rs = st.executeQuery(astring)
          
            if(rs.next())
            {
               java.sql.Blob ablob = rs.getBlob("MYBLOB");
               Bitmap bmp = BitmapFactory.decodeStream(ablob.getBinaryStream());
          
               // here you have your bmp, do whatever you want
               UseBmp(bmp);
            }
          
          }
          catch(Exception e)
          {
            e.printStackTrace();
          }
          

          您需要实现一个连接池来加快查询响应时间,因为 JDBC 在建立与服务器的连接时会给 Android 带来一点开销,需要 2 到 3 秒才能启动,但一旦连接运行速度非常快。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-06-11
            • 1970-01-01
            • 2012-05-06
            • 1970-01-01
            • 2012-05-29
            • 1970-01-01
            • 1970-01-01
            • 2012-03-12
            相关资源
            最近更新 更多