8

저는 Android에서 작업중인 프로젝트에서 내 네트워크 스택으로 Volley를 사용하고 있습니다. 필자의 요구 사항 중 하나는 잠재적으로 매우 큰 파일을 다운로드하여 파일 시스템에 저장하는 것입니다.발리 - 직접 파일로 다운로드 (메모리 바이트 배열 없음)

필자는 발리의 구현에서 찾고, 유일한 방법 헤딩슛은이 잠재적으로 대규모 바이트 배열에 전체 파일을 다운로드 한 후 일부 콜백 핸들러이 바이트 배열의 처리를 연기입니다 작동하는 것 같다.

이러한 파일은 매우 클 수 있으므로 다운로드 프로세스 중에 메모리 부족 오류가 발생합니다.

http 입력 스트림의 모든 바이트를 파일 출력 스트림으로 직접 처리하도록 volley에게 지시하는 방법이 있습니까? 아니면 내 자신의 네트워크 개체를 구현해야합니까?

온라인에 대한 자료를 찾을 수 없으므로 어떤 제안이라도 감사하겠습니다.

답변

3

좋아, 그럼 내가 Volley 자체 편집과 관련된 솔루션을 생각해 냈습니다. 다음은 살펴볼 내용입니다.

네트워크 응답은 더 이상 바이트 배열을 포함 할 수 없습니다. 입력 스트림을 보유해야합니다. 이렇게하면 공용 바이트 배열 멤버를 보유한 NetworkResponse에 의존하므로 모든 요청 구현이 즉시 중단됩니다. NetworkResponse 안에 "toByteArray"메서드를 추가 한 다음 조금 리팩터링하여 제거 된 바이트 배열 멤버가 아닌이 메서드를 사용하여 바이트 배열에 대한 참조를 만드는 것입니다. 즉, 입력 스트림이 바이트 배열로 전환되는 것은 응답 구문 분석 중에 발생합니다. 나는 이것의 장기적인 효과가 무엇인지에 대해 확신 할 수 없기 때문에 몇몇 단위 테스트/커뮤니티 입력이 큰 도움이 될 것입니다. 여기 코드는 다음과 같습니다

public class NetworkResponse { 
    /** 
    * Creates a new network response. 
    * @param statusCode the HTTP status code 
    * @param data Response body 
    * @param headers Headers returned with this response, or null for none 
    * @param notModified True if the server returned a 304 and the data was already in cache 
    */ 
    public NetworkResponse(int statusCode, inputStream data, Map<String, String> headers, 
      boolean notModified, ByteArrayPool byteArrayPool, int contentLength) { 
     this.statusCode = statusCode; 
     this.data = data; 
     this.headers = headers; 
     this.notModified = notModified; 
     this.byteArrayPool = byteArrayPool; 
     this.contentLength = contentLength; 
    } 

    public NetworkResponse(byte[] data) { 
     this(HttpStatus.SC_OK, data, Collections.<String, String>emptyMap(), false); 
    } 

    public NetworkResponse(byte[] data, Map<String, String> headers) { 
     this(HttpStatus.SC_OK, data, headers, false); 
    } 

    /** The HTTP status code. */ 
    public final int statusCode; 

    /** Raw data from this response. */ 
    public final InputStream inputStream; 

    /** Response headers. */ 
    public final Map<String, String> headers; 

    /** True if the server returned a 304 (Not Modified). */ 
    public final boolean notModified; 

    public final ByteArrayPool byteArrayPool; 
    public final int contentLength; 

    // method taken from BasicNetwork with a few small alterations. 
    public byte[] toByteArray() throws IOException, ServerError { 
     PoolingByteArrayOutputStream bytes = 
       new PoolingByteArrayOutputStream(byteArrayPool, contentLength); 
     byte[] buffer = null; 
     try { 

      if (inputStream == null) { 
       throw new ServerError(); 
      } 
      buffer = byteArrayPool.getBuf(1024); 
      int count; 
      while ((count = inputStream.read(buffer)) != -1) { 
       bytes.write(buffer, 0, count); 
      } 
      return bytes.toByteArray(); 
     } finally { 
      try { 
       // Close the InputStream and release the resources by "consuming the content". 
       // Not sure what to do about the entity "consumeContent()"... ideas? 
       inputStream.close(); 
      } catch (IOException e) { 
       // This can happen if there was an exception above that left the entity in 
       // an invalid state. 
       VolleyLog.v("Error occured when calling consumingContent"); 
      } 
      byteArrayPool.returnBuf(buffer); 
      bytes.close(); 
     } 
    } 

} 

그런 다음 우리가 (BasicNetwork.performRequest 내부에) 제대로 NetworkResponse을 만들 수있는 BasicNetwork을 편집 할 필요는 NetworkResponse을 준비 : 그것 뿐이다

int contentLength = 0; 
if (httpResponse.getEntity() != null) 
{ 
    responseContents = httpResponse.getEntity().getContent(); // responseContents is now an InputStream 
    contentLength = httpResponse.getEntity().getContentLength(); 
} 

... 

return new NetworkResponse(statusCode, responseContents, responseHeaders, false, mPool, contentLength); 

합니다. 일단 네트워크 응답 내의 데이터가 입력 스트림이라면, 작은 메모리 버퍼를 보유하고있는 파일 출력 스트림으로 직접 구문 분석 할 수있는 자체 요청을 작성할 수 있습니다.

몇 가지 초기 테스트에서 이것은 다른 구성 요소에 해를 끼치 지 않고 정상적으로 작동하는 것 같습니다. 그러나 이와 같은 변경에는 좀 더 집중적 인 테스트가 필요합니다. & 피어 검토 중이므로이 답변을 올바른 것으로 표시하지 않을 것입니다. 더 많은 사람들이 몸무게가 늘어나거나, 의지 할만 큼 강건하다는 것을 알았습니다.

언제든지이 답변에 댓글을 달거나 답변을 게시하십시오. 이것은 Volley의 디자인에 심각한 결함이있는 것처럼 느껴지며,이 디자인으로 결함을 보거나 더 나은 디자인을 생각할 수 있다면, 모든 사람에게 도움이 될 것이라고 생각합니다.

관련 문제