AWS Lambda и S3 - загруженный PDF-файл пуст / поврежден - PullRequest
2 голосов
/ 20 февраля 2020

У меня есть приложение Spring (работает на AWS Lambda), которое получает файл и загружает его на AWS S3.

Spring Controller отправляет MultipartFile моему методу, куда он загружается на AWS S3, используя Amazon API Gateway.

public static void uploadFile(MultipartFile mpFile, String fileName) throws IOException{

    String dirPath = System.getProperty("java.io.tmpdir", "/tmp");
    File file = new File(dirPath  + "/" + fileName);

    OutputStream ops = new FileOutputStream(file);
    ops.write(mpFile.getBytes());

    s3client.putObject("fakebucketname", fileName, file);

}

Я пытаюсь загрузить PDF-файл, содержащий 2 страницы с текстом. После загрузки файл PDF (на AWS S3) содержит 2 пустых страницы.

Почему загруженный файл PDF пуст?

Я также пытался использовать другие файлы (например, изображения PNG) и когда я открываю его, загруженное изображение повреждено.

Единственное, что сработало, это когда я загрузил текстовый файл.

Ответы [ 2 ]

1 голос
/ 28 февраля 2020

Оказывается, это поможет. Все дело в кодировании, благодаря помощи @KunLun. В моем сценарии файл - это составной файл (pdf), который передается в aws через POST в URL.

  • сервер получает файл с этим байтом -> 0010 (это не будет правильно интерпретировано, потому что стандартный байт имеет 8 бит)
  • , поэтому мы кодируем его в базе 64 - > не имеет значения, какой результат
  • расшифрует его, чтобы получить стандартный байт -> 0000 0010 (теперь это стандартный байт, и он интерпретируется как aws)
  • Этот источник помог здесь также много -> https://www.javaworld.com/article/3240006/base64-encoding-and-decoding-in-java-8.html?page=2
        Base64.Encoder enc = Base64.getEncoder();
        byte[] encbytes = enc.encode(file.getBytes());
        for (int i = 0; i < encbytes.length; i++)
        {
            System.out.printf("%c", (char) encbytes[i]);
            if (i != 0 && i % 4 == 0)
                System.out.print(' ');
        }
        Base64.Decoder dec = Base64.getDecoder();
        byte[] barray2 = dec.decode(encbytes);
        InputStream fis = new ByteArrayInputStream(barray2);

        PutObjectResult objectResult = s3client.putObject("xxx", file.getOriginalFilename(), fis, data);
1 голос
/ 21 февраля 2020

Могу ли я сказать, что я видел, как люди делали это, в результате чего их приложение принимает MultipartFile и прокси-сервер загружает его на S3.

Загрузка в ваше приложение, а затем на S3, честно говоря, является неправильным подходом и имеет множество недостатков, которые сводят на нет преимущества использования S3. Просто создайте предварительно подписанный URL-адрес и загрузите пользователя прямо на S3. Это предпочтительно по нескольким причинам, но основными из них являются:

  • Приложение, которое поддерживает загрузку MultipartFile, может быть легко обработано DDOS, если не соблюдать осторожность, это произошло с нашим приложением, когда кто-то загрузил много файлов на в то же время вся система вышла из строя.
  • Загрузка в ваше бэкэнд-приложение будет намного медленнее, а затем загрузка в S3.

Если вы использовали Cognito, вы также можете достичь это с 0 внутренним кодом, используя AWS Amplify. Который я очень рекомендую, но если нет, то предварительно подписанный URL - это путь к go.

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