如何在Spring MVC中通过Hibernate上传带有产品对象的图像



我有一个角度表单,我在其中填写产品的字段,然后选择图像。我在SpringMVC项目的AppConfig中添加了以下配置,以启用多部分文件。

@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 为内容类型附加了一个应用程序/json标头,我删除了它,因为它我得到了HTTP 状态 400 – 错误请求。 在这一点上,我不知道问题是什么,我不知道如何调试面向前端的弹簧 mvc 的东西,我只能通过控制器方法中的断点进行调试,但问题在之前就出现了。

我认为您必须发送多部分/相关请求,但上次我检查 Angular 不支持。

无论如何,您正在实现的代码比您需要的要多得多。 你为什么不看看春天的内容。 这旨在将内容与 Spring 数据实体相关联,就像您尝试的那样,使用与 Spring 数据相同(或非常相似的编程模型)。

您可以按如下方式将其添加到项目中:

绒球.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>

文件系统配置.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());
}
}

产品.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";
...
}

产品内容商店.java

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

这就是获取 REST 端点所需执行的全部操作,这些端点将允许您存储和检索与每个产品关联的内容。 这实际上是如何工作的,非常像Spring Data。 当你的应用程序启动时,Spring 内容将看到spring-content-fs-boot-starter依赖关系,并知道你想在文件系统上存储内容。 它将注入基于文件系统的ProductContentStore接口实现。 它还将看到spring-content-rest-boot-starter,并将注入与内容存储接口通信的 REST 端点。 这意味着您不必自己编写任何此类代码。

因此,例如:

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

将映像存储在文件系统上,并将其与 ID 为productId的产品实体相关联。

curl /productImages/{productId}

会再次获取它,依此类推...顺便说一句,实际上也支持完整的 CRUD 和视频流。

您还可以决定将内容存储在其他位置,例如数据库中(如某人评论的那样),或者通过将spring-content-fs-boot-starter依赖项交换为适当的 Spring 内容存储模块来存储在 S3 中。 此处提供了每种存储类型的示例。

总之,在撰写本文时,angular (和其他流行的前端)不支持multipart/related在我看来,这是上传与实体相关的内容的正确请求类型。 代替该 Spring 内容和您的解决方案将不得不使用单独的请求; 首先创建实体,其次将内容与该实体关联。

呵呵

相关内容

最新更新