Загрузка большого файла (>1 ГБ) в Grails3

При загрузке большого файла (> 1 ГБ) в Grails мне нужно получить к нему доступ только через поток, нет необходимости сохранять весь файл на диск или в ОЗУ. Однако как я могу получить доступ к потоку загрузки? Я пробовал с Interceptor:

class UploadLargeFileInterceptor {

int order = HIGHEST_PRECEDENCE

UploadLargeFileInterceptor() {
    match(controller:"apiv2", action:"uploadLarge")
}

boolean before() {

    log.error('before')
    log.error(request.getInputStream().text.length() as String)
    true
}

boolean after() {

    log.error('after')
    true
}

void afterView() {
    // no-op
}
}

но длина потока всегда равна 0, а в контроллере есть составной файл, которого я стараюсь избегать, потому что он будет хранить весь файл. Любые идеи?


person user39950    schedule 09.01.2018    source источник


Ответы (1)


Перехватчик не нужен. Вы можете получить доступ к загруженному пользователем файловому потоку, например, внутри контроллера:

MultipartFile uploadedFile = params.filename as MultipartFile
println "file original name" + uploadedFile.originalFilename
println "file content type" + uploadedFile.contentType
println "file size" + uploadedFile.size //consider as stream length
InputStream inputStream = uploadedFile.getInputStream() //access the input stream

Также не забудьте разрешить максимальный размер в application.groovy следующим образом:

grails.controllers.upload.maxFileSize = 1572864000 //1500MB (X MB * 1024 * 1024)
grails.controllers.upload.maxRequestSize = 1572864000 //1500MB

Или, если вы отстаете от веб-сервера, такого как nginx, также настройте этот запрос и конфигурацию тайм-аута.

С приведенным выше кодом и размером кучи -Xms512m -Xmx1G я без проблем загрузил файл размером 1,25 ГБ. Если вы загружаете в хранилище файлов/облачное хранилище, убедитесь, что lib использует поток, например:

Файл: org.apache.commons.io.FileUtils.copyToFile(inputStream, new File('<file path>')) Azure: storageBlob.upload(inputStream, length)

person Mamun Sardar    schedule 14.01.2018
comment
Это работает, потому что файл временно хранится на диске сервера. Но это то, чего я хочу избежать, я просто хочу получить дескриптор входного потока и пропустить его, а затем опустить - person user39950; 15.01.2018
comment
Я понимаю. Тогда все, о чем я могу думать, это то, что вам нужно полностью отключить multipartResolver grails, потому что он использует Spring CommonsMultipartResolver, который временно сохраняет загруженный в контейнер сервлета, когда размер определенного / конфигурации превышается, и очищается, когда заканчивается запрос пользователя. - person Mamun Sardar; 15.01.2018