Несоответствие размера загрузочного файла Spring Boot Multipart - PullRequest
1 голос
/ 28 июня 2019

У меня есть конечная точка, которая загружает файл изображения на сервер, затем на S3.

Когда я запускаю на localhost, размер байта MultipartFile правильный, и загрузка успешна.

Тем не менее, в момент, когда я развернул его на своем экземпляре EC2, размер загруженного файла неверен

Код контроллера

@PostMapping("/{id}/photos")
fun addPhotos(@PathVariable("id") id: Long,
              @RequestParam("file") file: MultipartFile,
              jwt: AuthenticationJsonWebToken) = ApiResponse.success(propertyBLL.addPhotos(id, file, jwt))

В методе PropertyBLL.addPhotos печать file.size приводит к неправильному размеру.

Фактический размер файла составляет 649305 байт, однако при загрузке на мой prod-сервер он читается как 1189763 байт.

  • Мой рабочий сервер является экземпляром AWS EC2, за Https.
  • Файлы yml приложения Spring одинаковы. Единственными конфигурациями, которые я переопределил, были свойства максимального размера файла.
  • Я использую PostMan для публикации запроса. Я передаю тело как данные формы, ключ с именем «файл».
  • Опять же, он отлично работает при локальном запуске.

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

Первые n байтов загруженного файла в редакторе Hex:

EFBFBD50 4E470D0A 1A0A0000 000D4948 44520000 03000000 02400802 000000EF BFBDCC96 01000000 0467414D 410000EF BFBDEFBF BD0BEFBF BD610500 00002063 48524D00 007A2600

Первые n байтов исходного файла:

89504E47 0D0A1A0A 0000000D 49484452 00000300 00000240 08020000 00B5CC96 01000000 0467414D 410000B1 8F0BFC61 05000000 20634852 4D00007A 26000080 840000FA 00000080

Похоже, они оба содержат текст «PNG», а также имеют конечный EXtdate: изменить / создать маркеры.

По запросу, основное содержимое addPhoto:

val metadata = ObjectMetadata()
metadata.contentLength = file.size
metadata.contentType = "image/png"
LOGGER.info("Uploading image of size {} bytes, name: {}", file.size, file.originalFilename)
val request = PutObjectRequest(awsProperties.cdnS3Bucket, imageName, file.inputStream, metadata)
awsSdk.putObject(request)

Это работает, когда я запускаю веб-сервер локально. imageName - это просто пользовательское имя. Существует другой код, включающий модели гибернации, но он не актуален.

Обновление

Это похоже на прокси Https / api. Когда я нажимаю http-адрес узла EC2, он работает нормально. Однако, когда я прохожу через прокси-сервер api (https://api.thedomain.com),, который проксирует узел EC2, происходит сбой. Я продолжу этот путь.

Ответы [ 2 ]

0 голосов
/ 28 июня 2019

После дополнительной отладки я обнаружил, что когда я POST непосредственно к экземпляру EC2, все работает, как ожидалось.Наш первичный и общедоступный URL-адрес отправляет запросы прокси через сервис API-шлюза Amazon.Этот сервис по какой-то причине преобразует данные в Base64, а не просто пропускает необработанные двоичные данные.

Я нашел документацию для обновления шлюза API для передачи двоичных данных: здесь .

Я использую значение Content-Type multipart/form-data.Не забудьте также добавить его в свои настройки API, где вы включаете двоичную поддержку.

Мне не нужно было редактировать параметры заголовков, кроме того, я использовал шаблон «Метод запроса по умолчанию».
Integration Example

И, наконец, не забудьте развернуть ваши изменения API ...

Теперь он работает как положено.

0 голосов
/ 28 июня 2019

Извините, но многие комментарии не имеют смысла. file.size вернет размер загруженного файла в байтах, а НЕ размер запроса (который, да, из-за различных фильтров потенциально может быть расширен за счет дополнительной информации и увеличения размера). Spring не может просто волшебным образом удвоить размер файла PNG (в вашем случае, добавив почти еще 600 КБ информации поверх того, что вы отправили). Хотя я хотел бы верить, что вы знаете, что делаете, и цифры, которые вы нам даете, действительно верны, для меня все доказательства указывают на человеческую ошибку ... пожалуйста, дважды, трижды, четыре раза проверьте, что вы действительно загружаете один и тот же файл во всех сценариях.

Как вы получили 649305 байт? Кто дал тебе этот номер? Был ли это ваш код или вы действительно посмотрели файл на диске и увидели его размер? Единственный способ обсуждения сжатия имеет смысл в этом контексте, если 649305 байт - это уже сжатый размер файла при локальном запуске (его фактический размер на диске составляет 1189763 байт), и, действительно, сжатие не включается при развертывании в AWS для некоторых причина, и вы получаете полный несжатый файл (мы даже не знаем, как вы его развертываете ... действительно ли он такой же, как локально? Вы используете автономный .jar в обоих случаях? Вы развертываете .war на AWS? возможно вместо этого? Вы действительно запускаете приложение в одном и том же контейнере и версии контейнера в обоих случаях, или вы, возможно, запускаете Tomcat локально и Jetty на AWS? и т. д. и т. д. и т. д.). Вы уверены, что ваш запрос почтальона не испортился, и вы не отправили что-то еще случайно (или больше, чем вы думаете)?

EDIT:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.sandbox</groupId>
    <artifactId>spring-boot-file-upload</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
package com.sandbox;

import static org.springframework.http.ResponseEntity.ok;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@SpringBootApplication
public class Application {

    public static void main(final String[] arguments) {
        SpringApplication.run(Application.class,
                              arguments);
    }

    @RestController
    class ImageRestController {

        @PostMapping(path = "/images")
        ResponseEntity<String> upload(@RequestParam(name = "file") final MultipartFile image) {
            return ok("{\"response\": \"Uploaded image having a size of '" + image.getSize() + "' byte(s).\"}");
        }
    }
}

Пример приведен на языке Java, поскольку его было проще собрать (среда представляет собой простую среду Java, в которой развернут автономный .jar - никаких дополнительных настроек или чего-либо еще, за исключением того, что порт сервера находится на 5000). В любом случае, вы можете попробовать это самостоятельно, отправив POST запросов на http://test123456.us-east-1.elasticbeanstalk.com/images

Это мой запрос почтальона и ответ с использованием предоставленного вами изображения:

enter image description here enter image description here

На моем экземпляре AWS EB все выглядит нормально, и все цифры складываются, как и ожидалось. Если вы говорите, что ваши настройки настолько просты, насколько это звучит, то я, к сожалению, так же озадачен, как и вы. Я могу только предположить, что вы уже поделились чем-то еще (однако я сомневаюсь, что проблема связана с Spring Boot ... тогда, скорее всего, это связано с вашими конфигурациями / настройками AWS).

...