Как преобразовать MultipartFile в требуемый тип byte [] - PullRequest
0 голосов
/ 01 мая 2019

Я работаю с пружиной Data-Jpa, используя пружинную загрузку. У меня есть многочастная форма для загрузки файла в базу данных с дополнительными полями, такими как (firstName, lastName, email, photo). Но я продолжаю получать это сообщение об ошибке для преобразования многочастного файла в требуемый тип byte []. Как я могу преобразовать файл изображения из составного файла в тип byte []?

Вот мой класс Controller:

    @PostMapping("/save")
public String saveUserWithPhoto(@ModelAttribute("user") User user,
                         @RequestParam("file") MultipartFile file) throws IOException {
    String fileName = StringUtils.cleanPath(file.getOriginalFilename());

    if (!(fileName == null) || fileName.contains("..")) {       
        byte[] photoBytes = file.getBytes();     
        user.setPhoto(photoBytes);
        userService.saveUserWithPhoto(user);
        return "redirect:/profile";
    }
    .......
    return "redirect:/new-user";

}

Вот мой сервисКласс:

  @Override
public void saveUserWithPhoto(User theUser){
    userRepository.save(theUser);
}

Вот мой EntityClass:

@Entity
@Table(name = "users")
public class User{

    @Id
    @GeneratedValue
    private long id;

    @Column(name = "first_name")
    private String firstName;

   @Column(name = "last_name")
    private String lastName;

    @Column(name = "email")
    private String email;

    @Lob
    @Column(name="photo")
    private byte[] photo;

}

Ответы [ 4 ]

0 голосов
/ 03 мая 2019

В качестве альтернативного подхода я бы порекомендовал вам взглянуть на проект сообщества Spring Content . Разработанный для решения именно вашей проблемы, этот проект предоставляет абстракцию для хранения неструктурированных данных, внедряет реализации служб и контроллеров для вас, так что вам не нужно реализовывать их самостоятельно, и позволяет связывать загруженный контент с вашими объектами Spring Data.

Кроме того, все модули хранения Spring Content, включая JPA, основаны на потоке и, следовательно, способны обрабатывать очень большие файлы, что не подходит для подхода byte[].

Добавление его в ваш проект будет выглядеть примерно так:

pom.xml (предполагается maven)

    <!-- Java API -->
    <!-- just change this depdendency if you want to store somewhere else -->
    <dependency>
        <groupId>com.github.paulcwarren</groupId>
        <artifactId>spring-content-jpa-boot-starter</artifactId>
        <version>0.8.0</version>
    </dependency>
    <!-- REST API -->
    <dependency>
        <groupId>com.github.paulcwarren</groupId>
        <artifactId>spring-content-rest-boot-starter</artifactId>
        <version>0.8.0</version>
    </dependency>

Определение хранилища контента (та же концепция, что и в хранилище данных Spring):

UserContentStore.java

  @StoreRestResource(path="photos")
  public interface UserPhotoStore extends ContentStore<User, UUID> {
  }

Свяжите контент с вашими User сущностями:

@Entity(name = "users")
public class User {
    @Id
    @GeneratedValue
    private long id;
    @Column(name = "first_name")
    private String firstName;
    @Column(name = "last_name")
    private String lastName;
    @Column(name = "email")
    private String email;

    // Spring Content annotations
    @ContentId
    private UUID contentId;

    @ContentLength
    private Long contentLen;

    @MimeType
    private String mimeType;

И это все. UserPhotoStore - это, по сути, универсальный Spring ResourceLoader. Зависимость spring-content-jpa-boot-starter заставит Spring Content внедрить реализацию этого интерфейса на основе jpa, а зависимость spring-content-rest-boot-starter заставит Spring Content внедрить реализацию @Controller, которая перенаправляет HTTP-запросы в методы UserPhotoStore. оказание услуг.

Теперь у вас будет полнофункциональная (POST, PUT, GET, DELETE) файловая служба на основе REST на /photoso/{userId}, которая будет использовать ваш UserPhotoStore для хранения (и извлечения) файлов в вашей базе данных и связывания их с вашими пользователями.

Итак:

curl -F ‘file=@/path/to/local/file.jpg’ /photos/{userId}

загрузит /path/to/local/file.jpg, сохранит его в вашей базе данных и свяжет с сущностью пользователя userId.

И

curl /photos/{userId}

восстановит его снова.

Контент может быть связан различными способами, как описано в документах (Шаблоны ассоциации).

НТН

0 голосов
/ 02 мая 2019

Я могу ошибаться, но я полагаю, что Spring пытается автоматически сопоставить весь объект «Пользователь», который передается в вашу конечную точку и не работает, потому что либо нет поля «фото» во входящем пользовательском объекте, или он не может автоматически преобразовать это поле в байт [].

Ради тестирования, если это так или нет, вы можете сделать одно из следующих 1) Если входящий пользовательский объект не имеет поля фотографии, удалите его из пользовательского объекта 2) Если это так, и он входит как MultipartFile, тогда измените с byte [] на multipartfile.

Я знаю, что ни один из них не поможет вам поместить его в базу данных, но это поможет выяснить, действительно ли это ваша проблема. Тогда я был бы рад помочь в дальнейшем.

EDIT

Хорошо, я усердно трудился, чтобы заставить это работать, и, наконец, я понял! Смотрите мои изменения ниже. Измените конечную точку контроллера следующим образом

@PostMapping
@ResponseBody
public void postUser(@ModelAttribute User user, @RequestParam("file") MultipartFile file) throws IOException {
        user.setPhotoByteArray(file.getBytes()); 
       //Do Service Call here(user)
    }

Я обновил объект User следующим образом.

@Entity(name = "users")
public class User {
    @Id
    @GeneratedValue
    private long id;
    @Column(name = "first_name")
    private String firstName;
    @Column(name = "last_name")
    private String lastName;
    @Column(name = "email")
    private String email;
    @Column(name = "photo")
    private byte[] photoByteArray;

    public User(long id, String firstName, String lastName, String email) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }

И это все! Я проверил эту работу, отправив запрос данных формы через почтальона со всеми необходимыми полями, я также добавил следующие строки, чтобы сохранить файл в локальном каталоге, чтобы я мог открыть его, чтобы убедиться, что он правильно обработал переданное мной изображение в почтальон

FileUtils.writeByteArrayToFile(new File("test.png"), user.getPhotoByteArray());

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

Дайте мне знать, если у вас по-прежнему будут проблемы или вопросы.

0 голосов
/ 02 мая 2019

Spring не хранит байты в самом классе, но вынуждает вас открыть поток из этого.

Содержимое файла хранится либо в памяти, либо временно на диске. В любом случае, пользователь несет ответственность за копирование содержимого файла в на уровне сеанса или постоянное хранилище, как и при желании. Временный хранилище будет очищено в конце обработки запроса.

Обычно я иду с промежуточным хранилищем в файл или в память со следующим кодом:

private final Path rootLocation;
try (InputStream inputStream = file.getInputStream()) {
  byte[] in = StreamUtils.copyToByteArray(inputStream);
  //Files.copy(inputStream, this.rootLocation.resolve(filename),
  //                StandardCopyOption.REPLACE_EXISTING);
}

Конечно, вы можете использовать все что угодно вместо создания байта [] из потока. Могу порекомендовать StreamUtils, если вы находитесь в Spring

0 голосов
/ 01 мая 2019

MultipartFile содержит byte array файла содержимого.Вы можете использовать метод getBytes().

в application.properties добавить:

spring.servlet.multipart.enabled=true

или использовать YAML можете добавить:

spring:
  servlet:
    multipart:
      enabled: true

и может получить байтовый массив из MultipartFile. Например:

MultipartFile  file;
//for your segment file fill from client side(in request)
byte [] content = file.getBytes();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...