当前位置: 首页 > 知识库问答 >
问题:

使用Axios将pdf文件从Vue前端上传到Spring后端

权兴为
2023-03-14

我在后端使用spring-boot 2.0.4,在前端使用vue 2.5.16 / axios 0.18.0,我希望将PDF文件上传到后端数据库,并从前端检索它们。

最初,我的灵感来自于spring部分的这个例子:https://grokonez . com/frontend/angular/angular-6/angular-6-client-upload-files-download-files-to-MySQL-with-spring boot-restapis

Axios部分的要点如下:https://gist.github.com/javilobo8/097c30a233786be52070986d8cdb1743

我的代码如下:

> < li>

使用axios在Vue中上传文件(使用" input type="file " "表单输入将this.file变量正确设置为my file,AxiosService()仅用于设置正确的baseUrl并包含带有令牌的授权头):

createRecord() {
  let formData = new FormData();
  formData.append("file", this.file);
  AxiosService()
    .post("/commands/material/", formData, {
       headers: {
         "Content-Type": "multipart/form-data"
       }
  })
  .then(response => {
    console.log("File uploaded");
  })
  .catch(error => {
    console.log(error);
  });

处理上传的Spring部分如下所示。在我的实体中,内容字段被定义为用@Lob注释的byte[]。

@BasePathAwareController
@RequestMapping("/commands/material")
public class MaterialCommandHandler {
    @Autowired
    MaterialRepository MaterialRepository;

    @RequestMapping(method=POST, path = "/")
    public ResponseEntity create(@RequestParam("file") MultipartFile file){
        MaterialEntity material = new MaterialEntity();
        material.setName(file.getOriginalFilename());
        material.setMimetype(file.getContentType());

        try {
            material.setContent(file.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            MaterialRepository.save(material);
        } catch (Exception e) {
            if (e instanceof DataIntegrityViolationException) {
                throw new InvalidCommandException("Data is invalid for creation.");
            }
            throw(e);
        }
        return ResponseEntity.status(HttpStatus.CREATED).body(material.getId());
}

使用这段代码,条目在数据库中正确创建,mysql中的内容字段的类型为longblob。

>

  • 为返回文件内容而定义的方法:

    @RequestMapping(method = GET, path = "/download/{fileId}")
    public ResponseEntity<byte[]> getFile(@PathVariable Long fileId) {
        Optional<MaterialEntity> fileOptional = materialRepository.findById(fileId);
    
        if(fileOptional.isPresent()){
            FrancaisMaterialEntity file = fileOptional.get();
            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachement; filename=\"" + file.getName() + "\"");
            return ResponseEntity.ok()
                .headers(headers)
                .body(file.getContent());
        }
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
    }
    

    最后,使用公有理从前端发送的 GET 方法:

    downloadFile() {
        AxiosService()
          .get(`/commands/material/download/${this.material.id}`, {
            responseType: "blob",
          })
          .then(response => {
            console.log(response);
            const url = window.URL.createObjectURL(new Blob([response.data]));
            const link = document.createElement("a");
            link.href = url;
            link.setAttribute("download", "CalculRanking.pdf");
            document.body.appendChild(link);
            link.click();
            link.parentNode.removeChild(link);
          })
          .catch(error => {
            console.log(error);
            this.errorMessage = error.response.data.message;
          });
      }
    

    尝试下载文件时,导航器中的弹出窗口显示正确,但不幸的是,下载的. pdf文件似乎已损坏,因为Chrome状态:“错误加载PDF文档失败”,我也无法在预览中打开它。

    我认为问题来自于在过程中的某个时候对内容的错误解释。我做了很多研究,但我尝试的解决方案都不起作用(我尝试的一些事情:添加值为“application/pdf”的“Accept”头,并在get请求中设置“responseType: arrayBuffer”),所以我决定在这里问这个问题。预先感谢你的帮助。

  • 共有2个答案

    伍成仁
    2023-03-14

    你为什么不看看Spring的内容呢。它的设计目的正是为了完成您想要做的事情,并将一个或多个内容对象与Spring数据实体关联起来。

    要将其添加到您现有的Spring启动项目中,请执行以下操作:

    pom.xml

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

    MaterialEntity.java

    @Entity
    public class MaterialEntity {
       @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="materialEntityContents")
    public interface MaterialEntityContentStore extends ContentStore<MaterialEntity, String> {
    }
    

    这就是获取RESTendpoint所需要做的一切,它将允许您存储和检索与每个MaterialEntity相关的内容。这实际上的工作原理非常类似于Spring Data。当您的应用程序启动时,Spring Content将看到sping-content-jpa-boot-starter依赖项,并知道您想将内容存储在数据库中。然后,它将在数据库中创建一个模式来执行此操作,并注入MaterialEntityContentStore接口的JPA实现。它还将看到sping-content-rest-boot-starter,并将注入与内容存储接口对话的RESTendpoint。这意味着您不必自己做任何事情。

    例如:

    卷曲 -X POST /材料实体内容/{材料实体 Id} -F “文件=@/路径/收件人/图像.jpg”

    会将图像存储在数据库中,并将其与 ID 为材料实体的材料实体相关联

    curl /materialEntityContents/{材料实体}

    将再次获取它等等...实际上也支持完整的CRUD和视频流。

    具体来说,这里有一个(非Spring靴)MySQL示例。

    您还可以决定将内容存储在其他地方,比如文件系统上,或者通过将< code > spring-Content-JPA-boot-starter 依赖项替换为适当的Spring内容存储模块,将内容存储在S3。这里是每种储物类型的示例。

    不幸的是,前端方面没有任何vuejs示例,但我们确实有一个角度js 1.x示例。这可能对前端有所帮助,因为它们是类似的技术(在我有限的经验中!

    和弘博
    2023-03-14

    你能改变你的方法得到文件

    @GetMapping("/download/{fileId}")
    @CrossOrigin
    @ResponseBody
    public ResponseEntity<InputStreamResource> getFile(@PathVariable(required = true, value = "fileId") Long fileId,
            HttpServletRequest request) throws IOException {
    
        Optional<MaterialEntity> fileOptional = materialRepository.findById(fileId);
        if (ensemblesRegles.isPresent()) {
            String fileName = "example.xlsx";
            MediaType mediaType = MediaType.parseMediaType("application/vnd.ms-excel");
            File file = new File(fileName); //the fileUtils is org.apache.commons.io.FileUtils;
            FileUtils.writeByteArrayToFile(file, fileOptional.get()); // Hope that your get return a byte[] array 
            InputStreamResource resource = new InputStreamResource(new FileInputStream(file));
    
            return ResponseEntity.ok()
                    // Content-Disposition
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + file.getName())
                    // Content-Type
                    .contentType(mediaType)
                    // Contet-Length
                    .contentLength(file.length()) //
                    .body(resource);
        }
        return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
    }
    
     类似资料:
    • 我正在努力使用axios将xml文件上载到我的asp。net服务器。我正在使用vue端的以下代码获取一个xml文件,该文件正在工作,然后将其上载到我的服务器: 在asp。net端我得到了这个函数: 上载文件会导致代码415:不支持的媒体类型。 我找到了一些建议将xml格式化程序添加到我的项目中,这不起作用,而且我不想解析xml文件,我只想将文件保存到我的文件系统中。 我尝试将原始文件和解析的文本与

    • 我正试图通过React将文件上载到s3存储桶,我正在与4xx和5xx进行斗争:( 下面是我的代码库: 如果我发了这篇文章,我会得到500英镑,而这个错误是: java.io.IOException:UT000036:解析多部分数据时连接终止 我还注意到documents属性为空: 这是后端的API文档: 谢谢!

    • 对于要添加到formData中的文本值,我使用类Blob,这样文件和文本值都是相同的。 在webservice java中,我有一个作为参数,并且只有文本值,我有我的数据。如果我在axios post请求中添加该文件,则会出现错误500并且服务器没有记录任何事件,我认为它会在与的映射中崩溃。 然后我尝试使用,但问题是一样的。 如果我像预期的那样只使用String作为param,那么在axios p

    • springboot接收前端上传到后端的文件时,在controller层内大多数使用的是MultipartFile进行接收的,当使用file进行接收时会报错 有大佬知道为啥不能用file接收文件吗?

    • 我试图发送一个csv文件到我的javaSpring启动后端。发送文件的代码如下: 以及从Spring Boot接受我的文件的代码: 然而,这似乎行不通。我一直收到一个错误,说当前请求不是一个多部分请求。有什么想法吗?

    • 我希望能够从开发和生产的前端直接将图像上传到ReactJS公共文件夹。对于生产,我使用带有nodejs后端的heroku应用程序。 从我在网上找到的所有使用ReactJS上传图像的教程中,他们都使用服务器端将图像上传到云,但我想知道是否有可能像Lavarel那样将图像上传到公共文件夹,这样做是否有任何缺点?