2017-01-26 2 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

Как это провал? Какие исключения возникают? Какие ошибки вы получаете? Вам нужно предоставить более подробную информацию. –

+0

@JoshuaMoore Я обновил более подробную информацию. – Anthony

+2

Попробуйте 'outputStream.flush()' перед возвратом из метода. –

ответ

1

Я думаю, комментарий Джошуа Мура, вероятно, правильный ответ.

Однако, я бы рекомендовал рефакторинг кода немного, чтобы сделать его немного чище.

1) Прежде всего старайтесь избегать передачи веб-объектов (например, запроса, ответа) на сервисный уровень. Вы можете реорганизовать это, указав метод уровня сервиса OutputStream. В методе службы вы просто создаете ByteArrayOutputStream, который будет содержать содержимое файла, загруженного с S3. Затем вы будете записывать содержимое этого выходного потока в 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 
    } 
Смежные вопросы