2012-10-03 3 views
1
결국

, 내 궁극적 목표는 다음과 같습니다 URL에서이상한 바이트 [] URL에서 읽기 동작

  • 읽기 (이 질문에 대해 무엇)
  • 저장을 검색 [PDF] DB의 BLOB 필드 내용 (이미 박살났다)
  • BLOB 필드에서 읽기 및 해당 내용을 전자 메일에 첨부하십시오.
  • 파일을 사용하지 않고 모두 시스템
다음과 같은 방법으로 목표는 이메일 첨부 파일로 다운 스트림 사용할 수있는 byte[]를 얻는 것입니다

는 (디스크에 쓰기 방지하기 위해) : 특정 PDF를 들어

public byte[] retrievePDF() { 

     HttpClient httpClient = new HttpClient(); 

     GetMethod httpGet = new GetMethod("http://website/document.pdf"); 
     httpClient.executeMethod(httpGet); 
     InputStream is = httpGet.getResponseBodyAsStream(); 

     byte[] byteArray = new byte[(int) httpGet.getResponseContentLength()]; 

     is.read(byteArray, 0, byteArray.length); 

     return byteArray; 
} 

getResponseContentLength() 방법을 길이로 101,689를 반환합니다. 이상한 부분은 내가 브레이크 포인트를 설정하고 byteArray 변수를 조사하면 101,689 바이트 요소를 가지지 만 바이트 # 3744 이후에는 배열의 나머지 바이트가 모두 0입니다 (0). 결과 PDF는 Adobe Reader와 같은 PDF 판독기 클라이언트에서 읽을 수 없습니다.

왜 그런가요?

브라우저를 통해이 같은 PDF를 검색 및 디스크에 저장, 또는 (내가 answer to this StackOverflow post 후에 모방하는) 다음과 같은 방법을 사용하여 읽을 수있는 PDF 결과 : 두 가지 접근 방식에 대한

public void retrievePDF() { 
    FileOutputStream fos = null; 
    URL url; 
    ReadableByteChannel rbc = null; 

    url = new URL("http://website/document.pdf"); 

    DataSource urlDataSource = new URLDataSource(url); 

    /* Open a connection, then set appropriate time-out values */ 
    URLConnection conn = url.openConnection(); 
    conn.setConnectTimeout(120000); 
    conn.setReadTimeout(120000); 

    rbc = Channels.newChannel(conn.getInputStream()); 

    String filePath = "C:\\temp\\"; 
    String fileName = "testing1234.pdf"; 
    String tempFileName = filePath + fileName; 

    fos = new FileOutputStream(tempFileName); 
    fos.getChannel().transferFrom(rbc, 0, 1 << 24); 
    fos.flush(); 

    /* Clean-up everything */ 
    fos.close(); 
    rbc.close(); 
} 

마우스 오른쪽 버튼 클릭> 속성 ... Windows에서 결과 PDF의 크기는 101,689 바이트입니다.

왜 바이트 배열은 본질적으로 부분적으로 "중지"됩니까?

답변

5

InputStream.readbyteArray.length 바이트까지 읽을 수 있지만 그만큼 정확하게 읽을 수는 없습니다. 읽은 바이트 수를 반환합니다. 사용자는이 같은 데이터를 읽을 반복적으로 호출해야합니다 :

int bytesRead = 0; 
while (true) { 
    int n = is.read(byteArray, bytesRead, byteArray.length); 
    if (n == -1) break; 
    bytesRead += n; 
} 
+0

bytesRead> = byteArray.length 일 경우 어떻게됩니까? 제로가 반환 될 것이며 무한 루프에 빠지게 될 것이라고 생각합니다. – Dunes

+0

수정하십시오. 여기서는 스트림의 byteArray.length> = total 바이트 (이 경우 서버가 제공 한 콘텐츠 길이를 기반으로 함)를 가정합니다. 따라서 서버가 악의적 인 내용으로 콘텐츠 길이에 대해 거짓말을하기로 결정한 경우 이론적으로는 가능하지만 그렇지 않을 수 있습니다. –

+0

나는이 방법을 시도했는데 97,943 바이트가 더 많았지 만 배열은 나머지 101,689 바이트를 여전히 0으로 표시합니다. 또한 결과 PDF가 열리지 않습니다. – PattMauler

0

InputStream.read의 반환 값을 확인하십시오. 그것은 한 번에 모든 것을 읽지 않을 것입니다. 루프를 작성해야합니다. 또는 더 나은 방법은 Apache Commons IO를 사용하여 스트림을 복사하는 것입니다.

0

101689 = 2^16 + 36,153 그래서 버퍼 크기에 16 비트 제한이 있다는 같을 것이다. 36153과 3744의 차이는 여분의 작은 1K 버퍼에서 읽힌 헤더 부분에서 비롯된 것이며 이미 몇 바이트를 포함하고 있기 때문일 수 있습니다.