2017-01-26 5 views
0

아래 코드를 사용하여 S3에서 파일을 다운로드하고 있습니다. 이 코드는 중형 및 대형 파일 크기에서 잘 작동하지만 다운로드가 실패하면 극히 작은 파일 크기 (3kb - TXT 파일에서 한 줄)가 발생합니다. 작은 파일작은 파일을 다운로드 할 수 없지만 큰 파일을 다운로드 할 수 있습니다.

// 컨트롤러

def download() { 
    Request request = Request.get(params.int("id")) 
    response.setContentType("application/octet-stream") 
    myService.downloadFileFromS3(request.origFileName, response) 
} 


void downloadFileFromS3(String fileName, HttpServletResponse response) { 
    String fullFileNameWithExtension = fileName 
    response.setHeader("Content-disposition", "attachment;filename=${fullFileNameWithExtension}") 
    InputStream is = getS3Client().getObject(getBucketName(), fullFileNameWithExtension).getObjectContent() 
    OutputStream outputStream = response.getOutputStream() 
    byte[] buffer = new byte[1024]; 
    int length 
    log.info("This is the length: " + length) 
    while ((length = is.read(buffer)) != -1) { 
     log.info("Came here with length: " + length) 
     outputStream.write(buffer, 0, length) 
    } 
    is.close() 
} 

로그 아웃 풋 :

This is the length: 0 
Came here with length: 15 
GroovyPagesServlet: "/WEB-INF/grails-app/views/request/download.gsp" not found 

로그 출력 큰 파일 :

This is the length: 0 
Came here with length: 1024 
Came here with length: 1024 
Came here with length: 1024 
Came here with length: 1024 
Came here with length: 1024 
Came here with length: 1024 
Came here with length: 1024 
Came here with length: 1024 
Came here with length: 1024 
Came here with length: 1024 
Came here with length: 1024 
Came here with length: 531 

은 그래서 작은 파일은 것 같다 download.gsp보기. 그러나 나는 물건을 넣고 있기 때문에 그 견해를 찾지 않아야한다. response

+0

방법이 실패하는 MyController에? 제기되는 예외는 무엇입니까? 어떤 오류가 있습니까? 자세한 내용을 제공해야합니다. –

+0

@JoshuaMoore 자세한 내용을 업데이트했습니다. – Anthony

+2

메소드에서 돌아 오기 전에'outputStream.flush()'를 시도하십시오. –

답변

1

나는 Joshua Moore의 의견이 아마도 정답이라고 생각한다.

그러나 조금 깔끔하게하기 위해 코드를 약간 리팩토링하는 것이 좋습니다.

1) 우선 웹 관련 객체 (예 : 요청, 응답)를 서비스 계층에 전달하지 않도록하십시오. 서비스 레이어 메서드가 OutputStream을 리턴하도록함으로써 이것을 리펙토링 할 수 있습니다. 서비스 메소드에서 S3에서 다운로드 한 파일의 내용을 보유 할 ByteArrayOutputStream을 작성하기 만하면됩니다. 그런 다음 해당 출력 스트림의 내용을 컨트롤러 내의 response.outputStream에 씁니다. 이렇게하면 코드 DRY를 테스트하고 유지하는 것이 더 쉬워집니다 (즉,이 방법을 사용하여 파일 내용을 응답에 기록하지 않고도 S3에서 파일을 다운로드 할 수 있습니다).

2) request은 암시 적 변수이므로 컨트롤러 메서드에 선언 된 변수의 이름을 request으로 변경해야합니다.

이면 MyService

def amazonWebService 
OutputStream downloadFileFromS3(String filename) { 
    InputStream inputStream = amazonWebService.getS3("us-east-1").getObject(getBucketName(), filename).getObjectContent() 
    OutputStream outputStream = new ByteArrayOutputStream() 
    byte[] buffer = new byte[1024]; 
    int length 
    log.info("This is the length: " + length) 
    while ((length = inputStream.read(buffer)) != -1) { 
     log.info("Came here with length: " + length) 
     outputStream.write(buffer, 0, length) 
    } 
    if (inputStream) inputStream.close() 
    return outputStream 
} 

def myService 
    def download() { 

     // NOTE: I would recommend not using `request` as a variable 
     // name here since it's already an implicit variable 
     Request thatOtherRequest = Request.get(params.int("id")) 

     def filename = thatOtherRequest.origFileName 
     def outputStream = myService.downloadFileFromS3UsingAwsSdk(filename) 

     response.setContentType("application/octet-stream") 
     response.setHeader("Content-disposition", "attachment;filename=${filename}") 
     response.outputStream << outputStream 
     response.outputStream.flush() 
     return 
    } 
관련 문제