2017-01-26 2 views
0

Ich verwende den folgenden Code, um Dateien von S3 herunterzuladen. Der Code funktioniert gut für mittlere bis große Dateigrößen, aber für extrem kleine Dateigrößen (3kb - eine Zeile in der TXT-Datei) schlägt der Download fehl.Nicht in der Lage, kleine Dateien herunterzuladen, aber große Dateien herunterladen

// Controller

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() 
} 

Abmelden put für kleine Dateien:

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

Log-Ausgang für große Dateien:

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 

So scheint es, dass für kleine Dateien, es ist Suchen nach download.gsp Ansicht. Aber es sollte nicht nach dieser Ansicht suchen, da ich Zeug in die

+0

Wie funktioniert es nicht? Welche Ausnahmen werden ausgelöst? Welche Fehler bekommst du? Sie müssen mehr Details angeben. –

+0

@JoshuaMoore Ich habe mit mehr Details aktualisiert. – Anthony

+2

Probieren Sie eine 'outputStream.flush()', bevor Sie von der Methode zurückkehren. –

Antwort

1

Ich denke, Joshua Moores Kommentar ist wahrscheinlich die richtige Antwort.

Allerdings würde ich empfehlen, den Code leicht zu refactoring, um es ein wenig sauberer zu machen.

1) Versuchen Sie zunächst einmal, web-bezogene Objekte (wie Request, Response) an die Service-Schicht zu übergeben. Sie können dies umgestalten, indem Ihre Service-Layer-Methode einen OutputStream zurückgibt. In der Service-Methode erstellen Sie einfach einen ByteArrayOutputStream, der den Inhalt der von S3 heruntergeladenen Datei enthält. Dann schreiben Sie den Inhalt dieses Ausgabestroms in den Controller unter response.outputStream. Dadurch wird es einfacher, den Code DRY zu testen und zu behalten (d. H., Sie können diese Methode jetzt verwenden, um eine Datei von S3 herunterzuladen, ohne das mit dem Schreiben der Dateiinhalte in die Antwort zu verbinden).

2) Sie sollten auch die in der Controller-Methode deklarierte request Variable umbenennen, da request eine implizite Variable ist.

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 
    } 
Verwandte Themen