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

今天花一天時間折騰Spring Boot+vue.js+axios文件浦旱,還好最算是弄成功了雄坪,在這里做個詳細的筆記砖瞧!

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

先看看表結構

本次實現(xiàn)思路是這樣的,兩張表足画,文件表和產(chǎn)品表雄驹,上傳時,在產(chǎn)品表中存文件表的ID即可淹辞,文件表中存文件的名稱医舆、路徑等信息。表結構如下:

產(chǎn)品表:product


product.png

文件表:product_doc


producrDoc.png

前端界面

<!--@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) {
                            // 然后還原數(shù)據(jù),使得輸入部分回到上傳前的狀態(tài)
                            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>發(fā)布新構件</title>

    <div class="panel panel-primary">
        <div class="panel-heading">
            <h3 class="panel-title">發(fā)布構件</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="發(fā)布" 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;

    /**
     * 主鍵關聯(lián)里烦,指向文檔表的主鍵ID
     * CascadeType.ALL->ALL 級聯(lián)/添加/更新/刪除
     */
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "docid")
    private ProductDoc productDoc;

    /**
     * 如果既沒有指明 關聯(lián)到哪個Column,又沒有明確要用@Transient忽略凿蒜,那么就會自動關聯(lián)到表對應的同名字段
     */
    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;
    
    /**
    *添加數(shù)據(jù)
    */
    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()

/**
     * 發(fā)布
     * @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);
        //文件路徑不存在時創(chuàng)建
        if (!filename.getParentFile().exists()) {
            filename.getParentFile().mkdirs();
        }
        //保存文件
        doc.transferTo(filename);
        //把文件名放在model里胁黑,以便后續(xù)顯示用
        model.addAttribute("Filename", Filename);
    }
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市州泊,隨后出現(xiàn)的幾起案子丧蘸,更是在濱河造成了極大的恐慌,老刑警劉巖遥皂,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件力喷,死亡現(xiàn)場離奇詭異,居然都是意外死亡演训,警方通過查閱死者的電腦和手機弟孟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來样悟,“玉大人拂募,你說我怎么就攤上這事】咚” “怎么了陈症?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長震糖。 經(jīng)常有香客問我录肯,道長,這世上最難降的妖魔是什么吊说? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任论咏,我火速辦了婚禮,結果婚禮上颁井,老公的妹妹穿的比我還像新娘潘靖。我一直安慰自己,他們只是感情好蚤蔓,可當我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布卦溢。 她就那樣靜靜地躺著,像睡著了一般秀又。 火紅的嫁衣襯著肌膚如雪单寂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天吐辙,我揣著相機與錄音宣决,去河邊找鬼。 笑死昏苏,一個胖子當著我的面吹牛尊沸,可吹牛的內容都是我干的威沫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼洼专,長吁一口氣:“原來是場噩夢啊……” “哼棒掠!你這毒婦竟也來了?” 一聲冷哼從身側響起屁商,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤烟很,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蜡镶,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體雾袱,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年官还,在試婚紗的時候發(fā)現(xiàn)自己被綠了芹橡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡望伦,死狀恐怖林说,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情屡谐,我是刑警寧澤述么,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站愕掏,受9級特大地震影響度秘,放射性物質發(fā)生泄漏。R本人自食惡果不足惜饵撑,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一剑梳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧滑潘,春花似錦垢乙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至粹舵,卻和暖如春钮孵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背眼滤。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工巴席, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人诅需。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓漾唉,卻偏偏與公主長得像荧库,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子赵刑,可洞房花燭夜當晚...
    茶點故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內容