为了账号安全,请及时绑定邮箱和手机立即绑定

如何将 MultipartFile 转换为所需的类型 byte[]

如何将 MultipartFile 转换为所需的类型 byte[]

手掌心 2022-11-02 16:10:57
我正在使用 Spring Boot 使用 Spring Data-Jpa。我有一个多部分表单将文件上传到数据库,其中包含附加字段,例如(名字、姓氏、电子邮件、照片)。但我不断收到此错误消息,用于将多部分文件转换为所需的字节 [] 类型。如何将图像文件从多部分文件转换为 byte[] 类型?这是我的控制器类:    @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";}这是我的服务类:  @Overridepublic void saveUserWithPhoto(User theUser){    userRepository.save(theUser);}这是我的实体类:@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 回答

?
绝地无双

TA贡献1946条经验 获得超4个赞

MultipartFile包含一个byte array内容文件。您可以使用 fromgetBytes()方法。


在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();


查看完整回答
反对 回复 2022-11-02
?
函数式编程

TA贡献1807条经验 获得超9个赞

作为替代方法,我建议您查看社区项目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 Data Repository 的概念相同):


用户内容存储.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 注入该spring-content-jpa-boot-starter 接口的基于 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}


将再次检索它。


内容可以按照文档(关联模式)中描述的各种方式关联。


高温高压


查看完整回答
反对 回复 2022-11-02
?
慕村9548890

TA贡献1884条经验 获得超4个赞

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);

}

当然,您可以使用任何您喜欢的东西来从流中创建 byte[]。如果你在春天,可以推荐 StreamUtils


查看完整回答
反对 回复 2022-11-02
?
素胚勾勒不出你

TA贡献1827条经验 获得超9个赞

我可能弄错了,但我相信 Spring 正在尝试自动映射传递到您的端点的整个“用户”对象并且失败,因为传入的用户对象中没有“照片”字段,或者它是无法将该字段自动转换为字节 []。


为了测试是否是这种情况,您可以执行以下操作之一 1)如果传入的 User 对象没有照片字段,请将其从您的 User 对象中删除 2)如果有并且它正在进来作为 MultipartFile 然后从 byte[] 更改为 multipartfile。


我知道这些都不能帮助您将其输入数据库,但它会帮助您确定这是否真的是您的问题。那么我很乐意提供进一步的帮助。


编辑


好的,我一直在努力让它工作,最后我得到了它!请参阅下面的更改。像这样更改控制器端点


@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());

我还向您的实体添加了一个构造函数,当它从模型属性创建对象时,它将允许它开始为空,我可以稍后设置它。


如果您仍有问题或疑问,请告诉我。


查看完整回答
反对 回复 2022-11-02
  • 4 回答
  • 0 关注
  • 572 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号