今天花一天时间折腾Spring Boot+vue.js+axios文件,还好最算是弄成功了,在这里做个详细的笔记!

Spring Boot+vue.js+axios文件上传

###先看看表结构 本次实现思路是这样的,两张表,文件表和产品表,上传时,在产品表中存文件表的ID即可,文件表中存文件的名称、路径等信息。表结构如下:

产品表:product

文件表:product_doc

###前端界面

<!--@author: An_Zhongqi-->
<div th:fragment="html">
    <script>
        $(function () {
            var time = new Date();
            var nowTime = time.toLocaleString();
            var data4Vue = {
                /**
                 * file表示要上传的附件
                 */
                uri: 'topublish',
                result: [],
                component: {
                    id: 0,
                    name: ''
                    category: {'id': 0},
                },
                categorys: [],
                categoryy: {id: 0, name: ''},
                file:null,
            };
            //ViewModel
            var vue = new Vue({
                el: '#workingArea',
                data: data4Vue,
                mounted: function () {
                    linkDefaultActions();
                },
                methods: {
                    publish: function () {
                        // 特殊字符校验
                        var regEn = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()——|{}【】‘;:”“'。,、?]");
                        if (0 == this.component.name.length) {
                            $("span.errorMessage").html("请输入构件名称");
                            $("div.registerErrorMessageDiv").css("visibility", "visible");
                            return;
                        }
                       
                        //axios.js 上传文件要用 formData 这种方式
                        var formData = new FormData();
                        var url = this.uri;
                        formData.append("doc", this.file);
                        formData.append("name", this.component.name);
                        axios.post(url, formData).then(function (response) {
                            // 然后还原数据,使得输入部分回到上传前的状态
                            var a=$("#categoryDoc").val('');
                            console.log(a)
                            vue.file = null;
                            $("#singlePic").val('');
                            vue.singleFile = null;
                            vue.component= {
                                id: 0,
                                    name: '',
                                    category: {'id': 0}
                            };
                            var result = response.data;
                            console.log(response.data.code);
                            if (result.code == 0) {
                                location.href = "publishSuccess";
                            }
                            else {
                                $("span.errorMessage").html(result.message);
                                $("div.registerErrorMessageDiv").css("visibility", "visible");
                            }
                        });

                    },
                    /**
                     * 当上传控件选中某个本地文件的时候,这个文件对象就会保存在data4Vue.file 上
                     * @param event
                     */
                    getFile: function (event) {
                        this.file = event.target.files[0];
                    },
                }
            });
        })
    </script>
    <title>发布新构件</title>

    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">发布构件</h3>
    </div>
        <div class="panel-body">
            <div style=" height: 35px;" class="registerErrorMessageDiv">
                <div class="alert alert-danger" role="alert">
                    <button type="button" class="close" data-dismiss="alert" aria-label="Close"></button>
                    <span class="errorMessage"></span>
                </div>
            </div>
            <div style="width: 70%;float: left" class="form-horizontal">
                <div class="form-group">
                    <label class="col-sm-5 control-label">构件名称</label>
                    <div class="col-sm-5">
                        <input v-model="component.name" type="text" class="form-control"
                               placeholder="请输入构件名称">
                    </div>
                </div>
               
                <div class="form-group">
                    <label class="col-sm-5 control-label">上传文件</label>
                    <div class="col-sm-5 custom-file">
                        <!--accept="application/msword"限制文件类型为doc-->
                        <input id="categoryDoc" accept="application/msword" type="file" name="doc" @change="getFile($event)" th:placeholder="选择相关文件" />
                        <p class="help-block">上传相关文件</p>
                    </div>
                </div>
                
                <div class="form-group">
                    <div class="col-sm-offset-7 col-sm-5">
                        <input type="submit" @click="publish" id="btn" value="发布" class="btn btn-primary">
                    </div>
                </div>
            </div>
        </div>
    </div>

</div>
复制代码

###实体类(Product.java)

package com.jeemia.component.pojo;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.springframework.data.elasticsearch.annotations.Document;

import javax.persistence.*;
import java.util.Date;
import java.util.List;

/**
 * @program: component
 * @author: An_Zhongqi
 **/
@Entity
@Table(name = "product")
@JsonIgnoreProperties({"handler", "hibernateLazyInitializer"})
@Document(indexName = "component", type = "product")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    int id;

    @ManyToOne
    @JoinColumn(name = "cid")
    private Category category;

    @ManyToOne
    @JoinColumn(name = "uid")
    private User user;

    /**
     * 主键关联,指向文档表的主键ID
     * CascadeType.ALL->ALL 级联/添加/更新/删除
     */
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "docid")
    private ProductDoc productDoc;

    /**
     * 如果既没有指明 关联到哪个Column,又没有明确要用@Transient忽略,那么就会自动关联到表对应的同名字段
     */
    private String name;

    @Transient
    private ProductImage firstProductImage;
    @Transient
    private List<ProductImage> productSingleImages;
    @Transient
    private List<ProductImage> productDetailImages;
    @Transient
    private int reviewCount;
    @Transient
    private int saleCount;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

   
    public ProductDoc getProductDoc() {
        return productDoc;
    }

    public void setProductDoc(ProductDoc productDoc) {
        this.productDoc = productDoc;
    }
}
复制代码

###实体类(ProductDoc)

package com.jeemia.component.pojo;

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import javax.persistence.*;
import java.util.List;

/**
* @author: An_Zhongqi
* @description: 构件的附属文件
* @create: 2019/4/24 15:11
*/
@Entity
@Table(name = "product_doc")
@JsonIgnoreProperties({ "handler","hibernateLazyInitializer"})
public class ProductDoc {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    public String name;
    private Float size;
    //文件路径
    private String folder;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Float getSize() {
        return size;
    }

    public void setSize(Float size) {
        this.size = size;
    }

    public String getFolder() {
        return folder;
    }

    public void setFolder(String folder) {
        this.folder = folder;
    }

}
复制代码

###Service(ProductService.java)

package com.jeemia.component.service;

import com.jeemia.component.dao.ProductDAO;
import com.jeemia.component.pojo.Category;
import com.jeemia.component.pojo.Product;
import com.jeemia.component.util.Page4Navigator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.List;

/**
 * @program: component
 * @author: An_Zhongqi
 **/
@Service
public class ProductService {
    @Autowired
    ProductDAO productDAO;
    @Autowired
    CategoryService categoryService;
    @Autowired
    ProductImageService productImageService;
    @Autowired
    OrderItemService orderItemService;
    @Autowired ReviewService reviewService;
    
    /**
    *添加数据
    */
    public void add(Product bean) {
        productDAO.save(bean);
    }

    public void delete(Product id) {
        productDAO.delete(id);
    }

    public void updata(Product bean) {
        productDAO.save(bean);
    }

    public Product get(int id) {
        return productDAO.findById(id).orElse(null);
    }

    public Page4Navigator<Product> list(int cid, int start, int size, int navigatePages) {
        Category category = categoryService.get(cid);
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        Pageable pageable = new PageRequest(start, size, sort);
        Page<Product> pageFromJPA = productDAO.findByCategory(category, pageable);
        return new Page4Navigator<>(pageFromJPA, navigatePages);
    }
}
复制代码

###Controller()

/**
     * 发布
     * @param product
     * @param productDoc
     * @param session
     * @param doc
     * @param model
     * @param request
     * @return
     * @throws Exception
     */
    @PostMapping("/topublish")
    public Object publish(Product product, ProductDoc productDoc, ProductImage productImage, HttpSession session,
                          MultipartFile doc, Model model, HttpServletRequest request) throws Exception {
        User user = (User) session.getAttribute("user");
        String filename = doc.getOriginalFilename();
        Long size1 = doc.getSize() / 1024;
        Float size = (float) size1;
        File fileFolder = new File(request.getServletContext().getRealPath("file/product"));
        String pictureFolder = iamgeFolder.toString();
        String folder = fileFolder.toString();
        
        product.setUser(user);
        product.setProductDoc(productDoc);
        product.setProductImage(productImage);
        product.setCreateDate(new Date());
        productService.add(product);
    
        saveOrUpdateDocFile(product, doc, request, model);
        productDoc.setName(filename);
        productDoc.setSize(size);
        productDoc.setFolder(folder);
        productDosService.add(productDoc);
        return Result.success();
    }

    /**
     * @param bean
     * @param doc
     * @param request
     * @param model   存放文件名,以备显示
     * @throws IOException
     */
    public void saveOrUpdateDocFile(Product bean, MultipartFile doc, HttpServletRequest request, Model model)
            throws IOException {
        //文件存放路径
        File fileFolder = new File(request.getServletContext().getRealPath("file/product"));
    	//获取上传的文件名
        String Filename = doc.getOriginalFilename();
        File filename = new File(fileFolder, Filename);
        //文件路径不存在时创建
        if (!filename.getParentFile().exists()) {
            filename.getParentFile().mkdirs();
        }
        //保存文件
        doc.transferTo(filename);
        //把文件名放在model里,以便后续显示用
        model.addAttribute("Filename", Filename);
    }
复制代码