2017-01-26 11 views
0

私は以下のコードを使用してS3からファイルをダウンロードしています。このコードは、中規模から大規模のファイルサイズではうまく機能しますが、ダウンロードが失敗すると、ファイルサイズが非常に小さい(3kb - TXTファイルで1行)場合に適しています。小さいファイルをダウンロードできませんが大きなファイルをダウンロードできます

//コントローラ

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

それがどのように失敗するのですか?どのような例外が発生していますか?あなたはどんなエラーを出していますか?詳細を提供する必要があります。 –

+0

@JoshuaMoore私は詳細を更新しました。 – Anthony

+2

メソッドから戻る前に 'outputStream.flush()'を試してください。 –

答えて

1

私はジョシュアムーアのコメントはおそらく正しい答えだと思います。

ただし、コードを少しリファクタリングして少しきれいにすることをおすすめします。

1)まず、Web関連のオブジェクト(リクエスト、レスポンスなど)をサービスレイヤに渡さないようにしてください。サービスレイヤメソッドで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 
} 

MyController

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 
    } 
関連する問題