今天花一天时间折腾Spring Boot+vue.js+axios文件,还好最算是弄成功了,在这里做个详细的笔记!
Spring Boot+vue.js+axios文件上传
本次实现思路是这样的,两张表,文件表和产品表,上传时,在产品表中存文件表的ID即可,文件表中存文件的名称、路径等信息。表结构如下:
产品表:product
Field | Type | Comment | |
---|---|---|---|
KEY | id | int(11) NOT NULL | 构件ID |
name | varchar(255) NULL | 构件名 | |
FK | docid | int(11) NULL | 外键指向文件ID |
文件表:product_doc
Field | Type | Comment | |
---|---|---|---|
KEy | id | int(11) NOT NULL | 文件ID |
name | char(255) NULL | 文件名 | |
folder | char(255) NULL | 文件路径 | |
size | float NULL | 文件大小 |
前端界面
1 <!--@author: An_Zhongqi--> 2 <div th:fragment="html"> 3 <script> 4 $(function () { 5 var time = new Date(); 6 var nowTime = time.toLocaleString(); 7 var data4Vue = { 8 /** 9 * file表示要上传的附件 10 */ 11 uri: 'topublish', 12 result: [], 13 component: { 14 id: 0, 15 name: '' 16 category: {'id': 0}, 17 }, 18 categorys: [], 19 categoryy: {id: 0, name: ''}, 20 file:null, 21 }; 22 //ViewModel 23 var vue = new Vue({ 24 el: '#workingArea', 25 data: data4Vue, 26 mounted: function () { 27 linkDefaultActions(); 28 }, 29 methods: { 30 publish: function () { 31 // 特殊字符校验 32 var regEn = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()——|{}【】‘;:”“'。,、?]"); 33 if (0 == this.component.name.length) { 34 $("span.errorMessage").html("请输入构件名称"); 35 $("div.registerErrorMessageDiv").css("visibility", "visible"); 36 return; 37 } 38 39 //axios.js 上传文件要用 formData 这种方式 40 var formData = new FormData(); 41 var url = this.uri; 42 formData.append("doc", this.file); 43 formData.append("name", this.component.name); 44 axios.post(url, formData).then(function (response) { 45 // 然后还原数据,使得输入部分回到上传前的状态 46 var a=$("#categoryDoc").val(''); 47 console.log(a) 48 vue.file = null; 49 $("#singlePic").val(''); 50 vue.singleFile = null; 51 vue.component= { 52 id: 0, 53 name: '', 54 category: {'id': 0} 55 }; 56 var result = response.data; 57 console.log(response.data.code); 58 if (result.code == 0) { 59 location.href = "publishSuccess"; 60 } 61 else { 62 $("span.errorMessage").html(result.message); 63 $("div.registerErrorMessageDiv").css("visibility", "visible"); 64 } 65 }); 66 67 }, 68 /** 69 * 当上传控件选中某个本地文件的时候,这个文件对象就会保存在data4Vue.file 上 70 * @param event 71 */ 72 getFile: function (event) { 73 this.file = event.target.files[0]; 74 }, 75 } 76 }); 77 }) 78 </script> 79 <title>发布新构件</title> 80 81 <div class="panel panel-primary"> 82 <div class="panel-heading"> 83 <h3 class="panel-title">发布构件</h3> 84 </div> 85 <div class="panel-body"> 86 <div style=" height: 35px;" class="registerErrorMessageDiv"> 87 <div class="alert alert-danger" role="alert"> 88 <button type="button" class="close" data-dismiss="alert" aria-label="Close"></button> 89 <span class="errorMessage"></span> 90 </div> 91 </div> 92 <div style="width: 70%;float: left" class="form-horizontal"> 93 <div class="form-group"> 94 <label class="col-sm-5 control-label">构件名称</label> 95 <div class="col-sm-5"> 96 <input v-model="component.name" type="text" class="form-control" 97 placeholder="请输入构件名称"> 98 </div> 99 </div> 100 101 <div class="form-group"> 102 <label class="col-sm-5 control-label">上传文件</label> 103 <div class="col-sm-5 custom-file"> 104 <!--accept="application/msword"限制文件类型为doc--> 105 <input id="categoryDoc" accept="application/msword" type="file" name="doc" @change="getFile($event)" th:placeholder="选择相关文件" /> 106 <p class="help-block">上传相关文件</p> 107 </div> 108 </div> 109 110 <div class="form-group"> 111 <div class="col-sm-offset-7 col-sm-5"> 112 <input type="submit" @click="publish" id="btn" value="发布" class="btn btn-primary"> 113 </div> 114 </div> 115 </div> 116 </div> 117 </div> 118 119 </div>
实体类(Product.java)
1 package com.jeemia.component.pojo; 2 3 import com.fasterxml.jackson.annotation.JsonFormat; 4 import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 import org.springframework.data.elasticsearch.annotations.Document; 6 7 import javax.persistence.*; 8 import java.util.Date; 9 import java.util.List; 10 11 /** 12 * @program: component 13 * @author: An_Zhongqi 14 **/ 15 @Entity 16 @Table(name = "product") 17 @JsonIgnoreProperties({"handler", "hibernateLazyInitializer"}) 18 @Document(indexName = "component", type = "product") 19 public class Product { 20 @Id 21 @GeneratedValue(strategy = GenerationType.IDENTITY) 22 @Column(name = "id") 23 int id; 24 25 @ManyToOne 26 @JoinColumn(name = "cid") 27 private Category category; 28 29 @ManyToOne 30 @JoinColumn(name = "uid") 31 private User user; 32 33 /** 34 * 主键关联,指向文档表的主键ID 35 * CascadeType.ALL->ALL 级联/添加/更新/删除 36 */ 37 @OneToOne(cascade = CascadeType.ALL) 38 @JoinColumn(name = "docid") 39 private ProductDoc productDoc; 40 41 /** 42 * 如果既没有指明 关联到哪个Column,又没有明确要用@Transient忽略,那么就会自动关联到表对应的同名字段 43 */ 44 private String name; 45 46 @Transient 47 private ProductImage firstProductImage; 48 @Transient 49 private List<ProductImage> productSingleImages; 50 @Transient 51 private List<ProductImage> productDetailImages; 52 @Transient 53 private int reviewCount; 54 @Transient 55 private int saleCount; 56 57 public int getId() { 58 return id; 59 } 60 61 public void setId(int id) { 62 this.id = id; 63 } 64 65 public Category getCategory() { 66 return category; 67 } 68 69 public void setCategory(Category category) { 70 this.category = category; 71 } 72 73 public User getUser() { 74 return user; 75 } 76 77 public void setUser(User user) { 78 this.user = user; 79 } 80 81 public String getName() { 82 return name; 83 } 84 85 public void setName(String name) { 86 this.name = name; 87 } 88 89 90 public ProductDoc getProductDoc() { 91 return productDoc; 92 } 93 94 public void setProductDoc(ProductDoc productDoc) { 95 this.productDoc = productDoc; 96 } 97 }
实体类(ProductDoc)
1 package com.jeemia.component.pojo; 2 3 import com.fasterxml.jackson.annotation.JsonBackReference; 4 import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 6 import javax.persistence.*; 7 import java.util.List; 8 9 /** 10 * @author: An_Zhongqi 11 * @description: 构件的附属文件 12 * @create: 2019/4/24 15:11 13 */ 14 @Entity 15 @Table(name = "product_doc") 16 @JsonIgnoreProperties({ "handler","hibernateLazyInitializer"}) 17 public class ProductDoc { 18 @Id 19 @GeneratedValue(strategy = GenerationType.IDENTITY) 20 @Column(name = "id") 21 private int id; 22 23 public String name; 24 private Float size; 25 //文件路径 26 private String folder; 27 28 public int getId() { 29 return id; 30 } 31 32 public void setId(int id) { 33 this.id = id; 34 } 35 36 public String getName() { 37 return name; 38 } 39 40 public void setName(String name) { 41 this.name = name; 42 } 43 44 public Float getSize() { 45 return size; 46 } 47 48 public void setSize(Float size) { 49 this.size = size; 50 } 51 52 public String getFolder() { 53 return folder; 54 } 55 56 public void setFolder(String folder) { 57 this.folder = folder; 58 } 59 60 }
Service(ProductService.java)
1 package com.jeemia.component.service; 2 3 import com.jeemia.component.dao.ProductDAO; 4 import com.jeemia.component.pojo.Category; 5 import com.jeemia.component.pojo.Product; 6 import com.jeemia.component.util.Page4Navigator; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.data.domain.Page; 9 import org.springframework.data.domain.PageRequest; 10 import org.springframework.data.domain.Pageable; 11 import org.springframework.data.domain.Sort; 12 import org.springframework.stereotype.Service; 13 14 import java.beans.PropertyDescriptor; 15 import java.util.ArrayList; 16 import java.util.List; 17 18 /** 19 * @program: component 20 * @author: An_Zhongqi 21 **/ 22 @Service 23 public class ProductService { 24 @Autowired 25 ProductDAO productDAO; 26 @Autowired 27 CategoryService categoryService; 28 @Autowired 29 ProductImageService productImageService; 30 @Autowired 31 OrderItemService orderItemService; 32 @Autowired ReviewService reviewService; 33 34 /** 35 *添加数据 36 */ 37 public void add(Product bean) { 38 productDAO.save(bean); 39 } 40 41 public void delete(Product id) { 42 productDAO.delete(id); 43 } 44 45 public void updata(Product bean) { 46 productDAO.save(bean); 47 } 48 49 public Product get(int id) { 50 return productDAO.findById(id).orElse(null); 51 } 52 53 public Page4Navigator<Product> list(int cid, int start, int size, int navigatePages) { 54 Category category = categoryService.get(cid); 55 Sort sort = new Sort(Sort.Direction.DESC, "id"); 56 Pageable pageable = new PageRequest(start, size, sort); 57 Page<Product> pageFromJPA = productDAO.findByCategory(category, pageable); 58 return new Page4Navigator<>(pageFromJPA, navigatePages); 59 } 60 }
Controller()
1 /** 2 * 发布 3 * @param product 4 * @param productDoc 5 * @param session 6 * @param doc 7 * @param model 8 * @param request 9 * @return 10 * @throws Exception 11 */ 12 @PostMapping("/topublish") 13 public Object publish(Product product, ProductDoc productDoc, ProductImage productImage, HttpSession session, 14 MultipartFile doc, Model model, HttpServletRequest request) throws Exception { 15 User user = (User) session.getAttribute("user"); 16 String filename = doc.getOriginalFilename(); 17 Long size1 = doc.getSize() / 1024; 18 Float size = (float) size1; 19 File fileFolder = new File(request.getServletContext().getRealPath("file/product")); 20 String pictureFolder = iamgeFolder.toString(); 21 String folder = fileFolder.toString(); 22 23 product.setUser(user); 24 product.setProductDoc(productDoc); 25 product.setProductImage(productImage); 26 product.setCreateDate(new Date()); 27 productService.add(product); 28 29 saveOrUpdateDocFile(product, doc, request, model); 30 productDoc.setName(filename); 31 productDoc.setSize(size); 32 productDoc.setFolder(folder); 33 productDosService.add(productDoc); 34 return Result.success(); 35 } 36 37 /** 38 * @param bean 39 * @param doc 40 * @param request 41 * @param model 存放文件名,以备显示 42 * @throws IOException 43 */ 44 public void saveOrUpdateDocFile(Product bean, MultipartFile doc, HttpServletRequest request, Model model) 45 throws IOException { 46 //文件存放路径 47 File fileFolder = new File(request.getServletContext().getRealPath("file/product")); 48 //获取上传的文件名 49 String Filename = doc.getOriginalFilename(); 50 File filename = new File(fileFolder, Filename); 51 //文件路径不存在时创建 52 if (!filename.getParentFile().exists()) { 53 filename.getParentFile().mkdirs(); 54 } 55 //保存文件 56 doc.transferTo(filename); 57 //把文件名放在model里,以便后续显示用 58 model.addAttribute("Filename", Filename); 59 } 60