我使用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-springboot-restapis
以及这个gist用于axios部分:https://gist.github.com/javilobo8/097c30a233786be52070986d8cdb1743
我的代码如下:
Uploading file in Vue with axios (the this.file variable is correctly set to my file using an "input type="file" " form input, AxiosService() is simply used to set the correct baseUrl and include an Authorization header with a token):
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); });
The spring part handling the upload looks as follow. In my Entity, the content field is defined as a byte[] annotated with @Lob.
@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类型。
The method defined to return the content of the file:
@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); }
Finally the GET method sent from the front-end using axios:
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; }); }