【问题标题】:Ways to proxy an InputStream代理 InputStream 的方法
【发布时间】:2016-03-19 18:42:50
【问题描述】:

我正在使用Android-Universal-Image-Loader 在我的Android 应用程序上通过HTTPS 从远程服务器加载图像。要访问图像,客户端应提供有效令牌,有时服务器可能会返回“过期 crsf 令牌”错误。为了处理此行为,应定义自定义 ImageDownloader。下面是在我的实现中应该被覆盖的方法的基本实现。

protected InputStream getStreamFromNetwork(String imageUri, Object extra) throws IOException {
    HttpURLConnection conn = createConnection(imageUri, extra);

    int redirectCount = 0;
    while (conn.getResponseCode() / 100 == 3 && redirectCount < MAX_REDIRECT_COUNT) {
         conn = createConnection(conn.getHeaderField("Location"), extra);
         redirectCount++;
    }

    InputStream imageStream;
    try {
         imageStream = conn.getInputStream();
    } catch (IOException e) {
         // Read all data to allow reuse connection (http://bit.ly/1ad35PY)
         IoUtils.readAndCloseStream(conn.getErrorStream());
         throw e;
    }
    if (!shouldBeProcessed(conn)) {
         IoUtils.closeSilently(imageStream);
         throw new IOException("Image request failed with response code " + conn.getResponseCode());
    }

    return new ContentLengthInputStream(new BufferedInputStream(imageStream, BUFFER_SIZE), conn.getContentLength());
}

我想重写它以处理无效令牌错误。例如,如果服务器返回这样的错误,它应该被识别,应该重新生成令牌并重复请求。

我想出的唯一解决方案是这样的(缩短的代码):

imageStream = conn.getInputStream();
byte[] body = org.apache.commons.io.IOUtils.toByteArray(imageStream);
if (body.length < 300  // high probability to contain err message
             && isInvalidToken(body)) {
              // handle error
}
return new ByteArrayInputStream(body);

考虑到我只将它用于最大 80kb 大小的缩略图,使用这种解决方案是否安全?还有其他解决方案吗?

【问题讨论】:

    标签: java android java-io


    【解决方案1】:

    你考虑过这样的事情吗?

    if(conn.getResponseCode()==HttpStatus.RESPONSE_OK) else{ //repeat request...} 
    

    【讨论】:

    • 问题是当有一个无效的token服务器会响应200 OK,只有HTTP响应体会提示错误。
    【解决方案2】:

    您可以在检查响应是否为 200 OK 后检查有效令牌,如下所示:

    conn.getResponseCode() == HttpStatus.RESPONSE_OK && isValidToken(body)
    

    如果不满足这些条件,则相应地处理它,即重复请求 x 次。

    我会考虑使用isValidToken(...) 方法而不是您的isInvalidToken(...),这样您就不必否定该方法的响应。

    【讨论】:

      【解决方案3】:

      您的解决方案是安全的,尽管如果您创建实现InputStream 并包装原始InputStreamImageDownloaderInputStream 类会更好。您可以从底层输入流中预加载(缓冲)一些块,以检测内容是否有效。

      您应该覆盖的唯一方法是read()

      如果内容有效,则可以将缓冲区内容提供给调用者,当缓冲区为空时,直接从底层InputStream流式传输。

      如果内容无效,只需读取另一个流,或返回零长度流。

      public class ImageDownloaderInputStream extends InputStream {
          private byte[] buffer = null;
          private int bufLen = 0;
          private int bufIndex = 0;
          private boolean isContentValid;
          private InputStream wrapped;
      
          public ImageDownloaderInputStream (InputStream wrapped) {
               this.wrapped = wrapped;
          }
      
          @Override
          public ind read() {
              if(buffer == null) {
                  // check content and fill buffer
                  this.isContentValid = checkContent();
              }
              if (this.isContentValid) {
                  if(bufIndex < bufLen) {
                      return buffer[bufIndex++] & 0xFF;
                  } else {
                       return wrapped.read();
                  }
              } else {
                  // error handling: zero-length stream
                  return -1;
              }
          }
      
          private boolean checkContent() {
              // fill the buffer
              this.buffer = new byte[1024];
              this.bufLen = wrapped.read(this.buffer); 
              // read more if not enough
      
              // check the content
              return true;
              // return false;      
          }
      }
      

      【讨论】:

      • 谢谢,这似乎是实现所描述任务的“正确”方法之一。
      • 您使用的是哪个 InputStream?我收到此错误:“InputStream 类型不能是 ImageDownloaderInputStream 的超接口;超接口必须是接口”
      • @Jose1755 哎呀,一个复制粘贴的问题,它是java.io.InputStream,因为它是一个抽象类,我们必须extend它。修复了上面的代码,希望你也能理解。
      猜你喜欢
      • 2015-07-31
      • 2017-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-31
      • 1970-01-01
      • 2012-11-05
      • 2021-09-16
      相关资源
      最近更新 更多