SpringBoot + zyupload :優(yōu)雅的實(shí)現(xiàn)網(wǎng)站文件上傳沟绪,用戶頭像自定義

前言:近期做網(wǎng)站項(xiàng)目遇到一個(gè)小功能刮便,實(shí)現(xiàn)網(wǎng)站用戶自定義上傳頭像,中間踩了很多坑绽慈,所以拿來分享一下恨旱,有涉及該類技術(shù)問題(SpringBoot項(xiàng)目文件上傳)可參考一下

1.開發(fā)前準(zhǔn)備

  • SpringBoot項(xiàng)目,SpringBoot基礎(chǔ)

  • zyupload插件(可去資源網(wǎng)站下載)


    zyupload
  • MySql 數(shù)據(jù)庫坝疼,自己定義用戶表(包含頭像路徑字段即可)

  • maven相關(guān)依賴 (僅展示io操作bufen)

        <!--io流-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>

  • 數(shù)據(jù)庫字段可參照下面 實(shí)體類 創(chuàng)建(Mybatis-plus)
package com.ht.webfront.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.Version;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

/**
 * <p>
 *  * 用戶實(shí)體類
 *  * </p>
 *  *
 *  * @author 掌灬紋
 *  * @since 2021-03-11
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="User對象", description="")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "自增id")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @ApiModelProperty(value = "用戶編號")
    private String uid;

    @ApiModelProperty(value = "角色編號")
    private Integer roleId;

    @ApiModelProperty(value = "用戶名")
    private String username;

    @ApiModelProperty(value = "密碼")
    private String password;

    @ApiModelProperty(value = "頭像")
    private String avatar;

    @ApiModelProperty(value = "登錄時(shí)間")
    private Date loginDate;

    @ApiModelProperty(value = "創(chuàng)建時(shí)間")
    @TableField(fill = FieldFill.INSERT)
    private Date gmtCreate;

    @ApiModelProperty(value = "修改時(shí)間")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date gmtModified;

    @ApiModelProperty(value = "版本號")
    @Version
    private Integer version;

    @ApiModelProperty(value = "邏輯刪除")
    @TableLogic
    private Integer deleted;

}

2. 定義上傳路徑常量(常量信息提人严汀)

package com.ht.webfront.persistence;

/**
 * 資源路徑枚舉
 */
public class ResourceConst {
    /**
     * 資源存儲(chǔ)根路徑
     */
    public static final String ROOT_PATH = "D:\\resources\\";

    // 視頻文件
    public static final String VIDEO = "video\\";

    // 圖片
    public static final String IMAGE = "image\\";

    // 文檔 xls xlsx
    public static final String DOCUMENT = "document\\";

    // avatar 特定頭像存放位置
    public static final String AVATAR = "avatar\\";

}

3.編寫簡易前端頁面 (含頭像展示,zyupload文件上傳插件即可钝凶,部分代碼示例)

        <!--頭像上傳-->
        <div class="col-md-9 blog-main">
            <div class="layuimini-container">
                <div class="layuimini-main">
                    <blockquote class="layui-elem-quote">
                        頭像上傳: <br>
                        僅支持 png jpg 格式單個(gè)圖片上傳仪芒,最大1MB(*^_^*)~
                    </blockquote>
                    <div id="zyupload" class="zyupload"></div>
                </div>
            </div>
        </div>

<script type="text/javascript">
    $(function () {
        // 初始化插件
        $("#zyupload").zyUpload({
            width: "650px",                 // 寬度
            height: "400px",                 // 寬度
            itemWidth: "140px",                 // 文件項(xiàng)的寬度
            itemHeight: "120px",                 // 文件項(xiàng)的高度
            url: "/user/avatarUpload",  // 上傳文件的路徑
            fileType: ["jpg", "png"],// 上傳文件的類型
            fileSize: 1048576,                // 上傳文件的大小
            multiple: false,                    // 是否可以多個(gè)文件上傳
            dragDrop: true,                    // 是否可以拖動(dòng)上傳文件
            tailor: true,                    // 是否可以裁剪圖片
            del: true,                    // 是否可以刪除文件
            finishDel: true,                  // 是否在上傳文件完成后刪除預(yù)覽
            /* 外部獲得的回調(diào)接口 */
            onSelect: function (selectFiles, allFiles) {    // 選擇文件的回調(diào)方法  selectFile:當(dāng)前選中的文件  allFiles:還沒上傳的全部文件
                /*                console.info("當(dāng)前選擇了以下文件:");
                                console.info(selectFiles);*/
            },
            onDelete: function (file, files) {              // 刪除一個(gè)文件的回調(diào)方法 file:當(dāng)前刪除的文件  files:刪除之后的文件
                alert("當(dāng)前刪除了圖片:" + file.name);
            },
            onSuccess: function (file, response) {          // 文件上傳成功的回調(diào)方法

                alert("頭像上傳成功:"+file.name);
                //$("#uploadInf").append("<p>上傳成功,文件地址是:" + response + "</p>");
            },
            onFailure: function (file, response) {          // 文件上傳失敗的回調(diào)方法
                alert("頭像上傳失敗:" + file.name);
            },
            onComplete: function (response) {                 // 上傳完成的回調(diào)方法
                alert("頭像上傳完成掂名!");
            }

        });
        return false;
    });
</script>

4.根據(jù)前端JS定義的上傳插件處理 URL路徑編寫控制器(/user/avatarUpload)

@Controller
public class UserController{
    @ResponseBody
    @PostMapping("/user/avatarUpload")
    public String doUploadAvatar(
            HttpServletRequest request,
            HttpServletResponse response,
            @RequestParam("file") MultipartFile file
    ){
        // 上傳根路徑
        String rootPath = ResourceConst.ROOT_PATH + ResourceConst.AVATAR;
        //文件名 后綴名
        String filename = file.getOriginalFilename();
        String suffix = filename.substring(filename.lastIndexOf("."));
        // 唯一文件名
        String uidFile = CupidUtils.getUuid() + suffix;

        //System.out.println(rootPath + " : " + uidFile);

        // 圖片上傳
        File target = new File(rootPath,uidFile);
        if (!target.exists()){
            target.mkdirs();
        }

        try {
            file.transferTo(target);
            // todo: 修改數(shù)據(jù)庫頭像位置信息
            User user = (User) request.getSession().getAttribute(LoginUser.LOGIN_USER_SESSION);
            // 獲取本地靜態(tài)資源路徑
            String localPath = "/staticmv/avatar/" + uidFile;
            user.setAvatar(localPath);
            userService.updateById(user);
            return "頭像上傳成功";
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "頭像上傳失斁萆颉!";
    }
}

5. 最關(guān)鍵饺蔑,配置SpringBoot 靜態(tài)資源路徑映射

  • mvc-config 配置
package com.ht.webfront.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class SpringMVCConfig implements WebMvcConfigurer {


    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/staticmv/**").addResourceLocations("file:///D:\\resources\\");
        //addResourceHandlers(registry);
    }
}

  • yml配置
#對外暴露 靜態(tài)資源接口
file:
  uploadFloder: D:/resources/
  staticAccessPath: /static/**
  common:
    uploadWindow: D:\resources\

6.可以測試了┗|`O′|┛ 嗷~~

(1).上傳圖片


界面.jpg
選擇文件.jpg

(2). mybatis-plus 控制臺(tái)打印日志(更新數(shù)據(jù)庫)


日志
數(shù)據(jù)庫字段修改

(3). 刷新頁面锌介,展示成果 ( :


頭像上傳成功
本地目錄

ps:文中相關(guān)資源可私信作者獲取~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市膀钠,隨后出現(xiàn)的幾起案子掏湾,更是在濱河造成了極大的恐慌,老刑警劉巖肿嘲,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件融击,死亡現(xiàn)場離奇詭異,居然都是意外死亡雳窟,警方通過查閱死者的電腦和手機(jī)尊浪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來封救,“玉大人拇涤,你說我怎么就攤上這事∮幔” “怎么了鹅士?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長惩坑。 經(jīng)常有香客問我掉盅,道長,這世上最難降的妖魔是什么以舒? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任趾痘,我火速辦了婚禮,結(jié)果婚禮上蔓钟,老公的妹妹穿的比我還像新娘永票。我一直安慰自己,他們只是感情好滥沫,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布侣集。 她就那樣靜靜地躺著,像睡著了一般兰绣。 火紅的嫁衣襯著肌膚如雪肚吏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天狭魂,我揣著相機(jī)與錄音,去河邊找鬼。 笑死雌澄,一個(gè)胖子當(dāng)著我的面吹牛斋泄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播镐牺,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼炫掐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了睬涧?” 一聲冷哼從身側(cè)響起募胃,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎畦浓,沒想到半個(gè)月后痹束,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡讶请,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年祷嘶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夺溢。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡论巍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出风响,到底是詐尸還是另有隱情嘉汰,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布状勤,位于F島的核電站鞋怀,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏荧降。R本人自食惡果不足惜接箫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望朵诫。 院中可真熱鬧辛友,春花似錦、人聲如沸剪返。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽脱盲。三九已至邑滨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間钱反,已是汗流浹背掖看。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工匣距, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人哎壳。 一個(gè)月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓毅待,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容