Как загрузить изображение с объектом продукта через Hibernate в Spring MVC - PullRequest
1 голос
/ 23 марта 2019

У меня есть угловая форма, в которой я заполняю поля для продукта, а затем выбираю изображения.Я добавил следующую конфигурацию в AppConfig в проекте SpringMVC, чтобы включить MultiPart Files.

@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
    CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
    multipartResolver.setMaxUploadSize(1000000);
    return multipartResolver;
}

Я также добавил переходное поле в моей модели продукта для таких изображений:

@Transient
private List<MultipartFile> productImages;

Так как я хочу получить объект Product отдельно внутри контроллера, я использую @RequestPart для извлечения обоих по отдельности, например:

@RequestMapping(value = "save", method = RequestMethod.POST)
public ResponseEntity addProduct(@Valid @RequestPart Product product, @RequestPart MultipartFile[] images, BindingResult bindingResult, HttpServletRequest 
}

А на внешнем интерфейсе внутри Angular я пытаюсь использовать FormData, чтобы помочь с этим.

let formData = new FormData();

formData.append('product', new Blob([JSON.stringify(this.product)],{ type: "application/json" }));
// I iterate and append all the images like this
formData.append('image[]', this.images, this.images.name);

this.http.post(this.appService.getApiUrl() + "api/product/save/", product);

Проблема в том, что всякий раз, когда я отправляю форму, я получаю это исключение в качестве ответа: Статус HTTP 415 - Неподдерживаемый тип носителя

У меня был HttpInterceptor, который добавил application / json заголовок для Content-Type , я удалил его, потому что получал HTTP Status 400 - Bad Request .На данный момент, я не знаю, в чем проблема, я не знаю, как отлаживать вещи mvc с передней пружиной, я могу отлаживать только через точки останова в методе контроллера, но проблема возникает задолго до этого.

1 Ответ

0 голосов
/ 25 марта 2019

Я думаю, вам нужно отправить запрос multipart / related , но в прошлый раз, когда я проверял Angular, это не поддерживалось.

В любом случае, вы реализуете гораздо больше кода, чем вам нужно. Почему бы вам не взглянуть на Spring Content . Это сделано для того, чтобы связать контент с объектами Spring Data, как вы пытаетесь сделать, используя ту же (или очень похожую модель программирования), что и Spring Data.

Вы можете добавить его в свой проект следующим образом:

pom.xml

   <!-- Java API -->
   <dependency>
      <groupId>com.github.paulcwarren</groupId>
      <artifactId>spring-content-fs-boot-starter</artifactId>
      <version>0.7.0</version>
   </dependency>

   <!-- REST API -->
   <dependency>
      <groupId>com.github.paulcwarren</groupId>
      <artifactId>spring-content-rest-boot-starter</artifactId>
      <version>0.7.0</version>
   </dependency>

FilesystemConfiguration.java

@Configuration
public class FilesystemConfiguration {

    @Bean
    File filesystemRoot() {
        try {
            return new File("/path/to/your/product/images");
        } catch (IOException ioe) {}
        return null;
    }

    @Bean
    FileSystemResourceLoader fileSystemResourceLoader() {
        return new FileSystemResourceLoader(filesystemRoot().getAbsolutePath());
    }
}

Product.java

@Entity
public class Product {
   @Id
   @GeneratedValue
   private long id;

   ...other existing fields...

   @ContentId
   private String contentId;

   @ContentLength
   private long contentLength = 0L;

   @MimeType
   private String mimeType = "text/plain";

   ...
}

ProductContentStore.java

@StoreRestResource(path="productImages")
public interface ProductContentStore extends ContentStore<Product, String> {
}

Это все, что вам нужно сделать, чтобы получить конечные точки REST, которые позволят вам хранить и извлекать контент, связанный с каждым продуктом. Как это на самом деле работает, очень похоже на Spring Data. Когда ваше приложение запустится, Spring Content увидит зависимости spring-content-fs-boot-starter и будет знать, что вы хотите хранить контент в файловой системе. Он внедрит основанную на файловой системе реализацию интерфейса ProductContentStore. Он также увидит spring-content-rest-boot-starter и введет конечные точки REST, которые взаимодействуют с интерфейсом хранилища контента. Это означает, что вам не нужно писать этот код самостоятельно.

Так, например:

curl -X POST /productImages/{productId} -F "file=@/path/to/image.jpg"

сохранит изображение в файловой системе и свяжет его с сущностью продукта с идентификатором productId.

curl /productImages/{productId}

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

Вы также можете решить хранить содержимое в другом месте, например, в базе данных (как кто-то прокомментировал) или в S3, поменяв местами зависимость spring-content-fs-boot-starter для соответствующего модуля Spring Content Storage. Примеры для каждого типа хранилища: здесь .

Итак, angular (и другие популярные интерфейсы) на момент написания статьи не поддерживают multipart/related, что, на мой взгляд, является правильным типом запроса на загрузку контента, связанного с сущностями. Вместо этого Spring Content и вашему решению придется использовать отдельные запросы к; во-первых, чтобы создать объект, а во-вторых, связать контент с этим объектом.

НТН

...