SpringBoot + zyupload :优雅的实现网站文件上传,用户头像自定义

前言:近期做网站项目遇到一个小功能,实现网站用户自定义上传头像,中间踩了很多坑,所以拿来分享一下,有涉及该类技术问题(SpringBoot项目文件上传)可参考一下

1.开发前准备

  • SpringBoot项目,SpringBoot基础

  • zyupload插件(可去资源网站下载)


    zyupload
  • MySql 数据库,自己定义用户表(包含头像路径字段即可)

  • maven相关依赖 (仅展示io操作bufen)

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

  • 数据库字段可参照下面 实体类 创建(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>
 *  * 用户实体类
 *  * </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 = "登录时间")
    private Date loginDate;

    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    private Date gmtCreate;

    @ApiModelProperty(value = "修改时间")
    @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 {
    /**
     * 资源存储根路径
     */
    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 格式单个图片上传,最大1MB(*^_^*)~
                    </blockquote>
                    <div id="zyupload" class="zyupload"></div>
                </div>
            </div>
        </div>

<script type="text/javascript">
    $(function () {
        // 初始化插件
        $("#zyupload").zyUpload({
            width: "650px",                 // 宽度
            height: "400px",                 // 宽度
            itemWidth: "140px",                 // 文件项的宽度
            itemHeight: "120px",                 // 文件项的高度
            url: "/user/avatarUpload",  // 上传文件的路径
            fileType: ["jpg", "png"],// 上传文件的类型
            fileSize: 1048576,                // 上传文件的大小
            multiple: false,                    // 是否可以多个文件上传
            dragDrop: true,                    // 是否可以拖动上传文件
            tailor: true,                    // 是否可以裁剪图片
            del: true,                    // 是否可以删除文件
            finishDel: true,                  // 是否在上传文件完成后删除预览
            /* 外部获得的回调接口 */
            onSelect: function (selectFiles, allFiles) {    // 选择文件的回调方法  selectFile:当前选中的文件  allFiles:还没上传的全部文件
                /*                console.info("当前选择了以下文件:");
                                console.info(selectFiles);*/
            },
            onDelete: function (file, files) {              // 删除一个文件的回调方法 file:当前删除的文件  files:删除之后的文件
                alert("当前删除了图片:" + file.name);
            },
            onSuccess: function (file, response) {          // 文件上传成功的回调方法

                alert("头像上传成功:"+file.name);
                //$("#uploadInf").append("<p>上传成功,文件地址是:" + response + "</p>");
            },
            onFailure: function (file, response) {          // 文件上传失败的回调方法
                alert("头像上传失败:" + file.name);
            },
            onComplete: function (response) {                 // 上传完成的回调方法
                alert("头像上传完成!");
            }

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

4.根据前端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: 修改数据库头像位置信息
            User user = (User) request.getSession().getAttribute(LoginUser.LOGIN_USER_SESSION);
            // 获取本地静态资源路径
            String localPath = "/staticmv/avatar/" + uidFile;
            user.setAvatar(localPath);
            userService.updateById(user);
            return "头像上传成功";
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "头像上传失败!";
    }
}

5. 最关键,配置SpringBoot 静态资源路径映射

  • 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配置
#对外暴露 静态资源接口
file:
  uploadFloder: D:/resources/
  staticAccessPath: /static/**
  common:
    uploadWindow: D:\resources\

6.可以测试了┗|`O′|┛ 嗷~~

(1).上传图片


界面.jpg
选择文件.jpg

(2). mybatis-plus 控制台打印日志(更新数据库)


日志
数据库字段修改

(3). 刷新页面,展示成果 ( :


头像上传成功
本地目录

ps:文中相关资源可私信作者获取~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,313评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,369评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,916评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,333评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,425评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,481评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,491评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,268评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,719评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,004评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,179评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,832评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,510评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,153评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,402评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,045评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,071评论 2 352

推荐阅读更多精彩内容