Частичная загрузка файла / поврежденного файла с amazon S3 springboot - PullRequest
0 голосов
/ 22 апреля 2020

У меня есть веб-приложение с весенней загрузкой, которое использует Amazon S3 для внутренних целей и предоставляет функции загрузки и скачивания файлов с некоторыми дополнительными полномочиями.

Ниже приведен код контроллера для загрузки файла

Контроллер . java

    @GetMapping ( "/{imageId}" )
public void downloadImage( @PathVariable ( "imageId") String imageId, @ApiIgnore HttpServletResponse response )
    throws IOException
{

    S3Object object = s3Client.getObject( new GetObjectRequest( awsBucket, imageId ) );
    InputStream inputStream = object.getObjectContent();
    int contentLength = Math.toIntExact( object.getObjectMetadata().getContentLength() );
    String contentType = object.getObjectMetadata().getContentType();


    response.setContentLength( contentLength );
    response.setContentType( contentType );
    IOUtils.copy( inputStream, response.getOutputStream() );

}

И затем я загружаю файл, получая входной поток, используя URL-адрес файла и IOUtils, как показано ниже.

    try {
        InputStream inputStream = /* Code to get the Input Stream using Http URL*/;
        byte[] bytes = IOUtils.toByteArray( inputStream );
        IOUtils.write( bytes, new FileOutputStream( "Path/to/my/local/file" ) );
    } catch ( IOException e ) {
        LOG.error( "Error occurred while performing operation in fetchImageURL", e );
    }

Загрузка довольно проста. Просто получите входной поток, считайте байты и запишите его в выходной поток локального файла.

Проблема, с которой я сталкиваюсь, заключается в том, что иногда (согласно моим наблюдениям , когда ЗАГРУЗКА ВЫСОКАЯ ), скачанный файл поврежден. Под поврежденным я имею в виду, скачанный файл иногда составляет 0 байт. или частично загруженный (например, 10 КБ, в то время как оригинал равен 50 КБ).

Я прочитал документацию s3Client.getObject( new GetObjectRequest( awsBucket, objectKey ) ) и подозреваю, что именно в этом проблема.

Получает объект, хранящийся в Amazon S3 в соответствии с указанным сегментом и ключом. Возвращает ноль, если указанные ограничения не были соблюдены. Будьте предельно осторожны при использовании этого метода; возвращенный объект Amazon S3 содержит прямой поток данных из HTTP-соединения. Базовое HTTP-соединение не может быть повторно использовано, пока пользователь не закончит чтение данных и не закроет поток. Также обратите внимание, что если не все данные считываются из потока, SDK прервет базовое соединение, что может отрицательно повлиять на производительность. Поэтому: как можно скорее используйте данные из входного потока в объекте Amazon S3. Считайте все данные из потока (используйте GetObjectRequest.setRange (long, long), чтобы запросить только нужные вам байты). Закройте входной поток в объекте Amazon S3 как как можно скорее Если эти правила не соблюдаются, клиент может исчерпать ресурсы, выделив слишком много открытых, но неиспользуемых HTTP-соединений. Чтобы получить объект из Amazon S3, вызывающий должен иметь доступ Permission.Read к объекту. Если извлеченный объект доступен для публичного чтения, он также может прочитать его, вставив свой URL в браузер. При указании ограничений в объекте запроса клиент должен быть готов обработать этот метод, возвращая значение null, если указанные ограничения не выполняются, когда Amazon S3 получает запрос. Если дополнительные параметры, предоставляемые в GetObjectRequest, не нужны, используйте более простой метод AmazonS3.getObject (String bucketName, String key). Если вы обращаетесь к AWS объектам, зашифрованным KMS, вам нужно указать правильный регион корзины на вашем клиенте и настроить AWS Signature Version 4 для дополнительной безопасности. Для получения дополнительной информации о том, как это сделать, см. http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingAWSSDK.html# define-signature-version

Итак, возможно ли, что s3Client.getObject( new GetObjectRequest( awsBucket, objectKey ) ) приведет к частичной загрузке / сбою при высокая загрузка ?

Другой вариант, который я вижу, - сначала загрузить файл S3 в память, а затем передавать данные из памяти, как указано в этом ответе . Это правильное решение для первой загрузки в память, а затем потоковой передачи? Я не уверен, что это решит мою проблему. Каковы недостатки этого (если таковые имеются)?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...