store(商城项目)Springboot+springmvc+ajax+mybatis(六)

23. 用户-上传头像-控制器层

在控制器层中,关于上传头像的代码:

/**
 * 允许上传的文件大小的上限值,以字节为单位
 */
private static final long AVATAR_MAX_SIZE = 101 * 1024;
/**
 * 允许上传的文件类型的集合
 */
private static final List<String> AVATAR_TYPES = new ArrayList<>();

static {
    AVATAR_TYPES.add("image/jpeg");
    AVATAR_TYPES.add("image/png");
    AVATAR_TYPES.add("image/gif");
    AVATAR_TYPES.add("image/bmp");
}

@PostMapping("avatar/change")
public JsonResult<String> changeAvatar(
    MultipartFile file, HttpSession session) {
    // 日志
    System.err.println("UserController.changeAvatar()");

    // 判断文件是否为空
    boolean isEmpty = file.isEmpty();
    System.err.println("\tisEmpty=" + isEmpty);
    if (isEmpty) {
        // 上传的文件为空,则抛出异常
        throw new FileEmptyException(
            "上传失败!请选择您要上传的文件!");
    }

    // 获取文件大小
    long size = file.getSize();
    System.err.println("\tsize=" + size);
    if (size > AVATAR_MAX_SIZE) {
        throw new FileSizeException(
            "上传失败!不允许上传超过" + 
                (AVATAR_MAX_SIZE / 1024) + "KB的文件!");
    }

    // 获取文件的MIME类型
    String contentType = file.getContentType();
    System.err.println("\tcontentType=" + contentType);
    // 判断上传的文件类型是否符合:image/jpeg,image/png,image/gif,image/bmp
    if (!AVATAR_TYPES.contains(contentType)) {
        throw new FileTypeException(
            "上传失败!仅允许上传以下类型的文件:" + AVATAR_TYPES);
    }

    // 获取原始文件名(客户端设备中的文件名)
    String originalFilename 
        = file.getOriginalFilename();
    System.err.println("\toriginalFilename=" + originalFilename);

    // 将文件上传到哪个文件夹
    String parent = session
        .getServletContext().getRealPath("upload");
    System.err.println("\tupload path=" + parent);
    File dir = new File(parent);
    if (!dir.exists()) {
        dir.mkdirs();
    }

    // 保存上传的文件时使用的文件名
    String filename = "" 
            + System.currentTimeMillis() 
            + System.nanoTime();
    String suffix = "";
    int beginIndex = originalFilename
            .lastIndexOf(".");
    if (beginIndex >= 1) {
        suffix = originalFilename
            .substring(beginIndex);
    }
    String child = filename + suffix;

    // 将客户端上传的文件保存到服务器端
    File dest = new File(parent, child);
    try {
        file.transferTo(dest);
    } catch (IllegalStateException e) {
        throw new FileUploadStateException(
            "上传失败!您的文件的状态异常!");
    } catch (IOException e) {
        throw new FileUploadIOException(
            "上传失败!读写文件时出现错误,请重新上传!");
    }

    // 将保存的文件的路径记录到数据库中
    String avatar = "/upload/" + child;
    System.err.println("\tavatar path=" + avatar);
    Integer uid = getUidFromSession(session);
    String username = getUsernameFromSession(session);
    userService.changeAvatar(uid, avatar, username);

    // 返回
    return new JsonResult<>(OK, avatar);
}

24. 用户-上传头像-前端页面

如果需要使用$.ajax()函数实现上传,在配置该函数的参数时,参数JSON对象的使用相对一般的数据提交有所区别,在于:

  1. data属性的值不再是$("表单").serialize(),而必须是new FormData(表单)

  2. 添加配置contentType属性,取值为false

  3. 添加配置processData属性,取值为false

为了使得打开页面时,就显示新上传的头像,应该将上传成功后得到的头像路径存储在本地!则需要使用Cookie技术!

在登录页面login.html的顶部引用了基于jQuery操作Cookie的文件:

<script src="../bootstrap3/js/jquery.cookie.js" type="text/javascript" charset="utf-8"></script>

而在上传头像页面upload.html中默认并没有引用该文件,所以,需要先在upload.html中补充引用以上文件!

在上传头像成功后,需要将头像路径保存到Cookie中:

// 将新图片的路径保存到Cookie中
$.cookie("avatar", json.data, {"expires":7});

并且,在该页面打开时,就应该读取保存的头像并显示到控件中:

$(document).ready(function() {
    // 尝试从Cookie中读取用户的头像
    let avatar = $.cookie("avatar");
    console.log("读取Cookie中的头像路径:" + avatar);
    // 将页面中的图片控件显示头像
    if (avatar != null) {
        $("#img-avatar").attr("src", avatar);
    }
});

最后,还应该在登录页面login.html中,当登录成功时,将用户的头像保存到Cookie中:

if (json.data.avatar == undefined) {
        $.cookie("avatar", null, {"expires":-1});
} else {
        $.cookie("avatar", json.data.avatar, {"expires":7});
}

25. 关于上传文件的补充

关于一次性上传多个文件

首先,应该考虑上传的文件的数量和文件的定位是否能直接确定,例如“上传身份证的正反两张照片”就属性是可确定的,而“发朋友圈”要上传的图片的数量就是无法确定的!

如果是可以确定的,则在页面中添加多个<input type="file">控件,然后,在控制器,声明多个MultipartFile类的参数即可!

如果是无法确定的,则在页面的控件<input type="file">中添加multiple="multiple"属性,则该控件是可以选择多个文件的,当用户操作时,按住键盘的Ctrl键就可以选择多个文件!由于只使用了1个控件,所以,多个文件提交到服务器后,会得到一个MultipartFile[]格式的数据,然后,检查数据并遍历数组即可处理!

关于在SpringMVC框架中处理文件上传

在使用SpringBoot框架时,已经添加了常用的依赖,并完成了常规的配置,所以,可以直接处理上传!在使用普通的SpringMVC框架时,首先,需要自行添加依赖:

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

然后,在Spring的配置文件中添加配置:

<bean id="multipartResolver" class="xx.xx.xx.CommonsMultipartResolver">
    <!-- 按需配置上传文件的大小限制 -->
    <!-- 按需配置字符编码 -->
</bean>

注意:以上配置中,<bean>节点的id必须是multipartResolver

最后,在处理请求时,参数列表中的MultipartFile file参数需要添加@RequestParam("file")注解!

26. 收货地址-创建数据表

 

CREATE TABLE t_address (
    aid INT AUTO_INCREMENT COMMENT '收货地址id',
    uid INT NOT NULL COMMENT '用户id',
    receiver VARCHAR(20) COMMENT '收货人',
    province_name VARCHAR(15) COMMENT '省名称',
    province_code CHAR(6) COMMENT '省代号',
    city_name VARCHAR(15) COMMENT '市名称',
    city_code CHAR(6) COMMENT '市代号',
    area_name VARCHAR(15) COMMENT '区名称',
    area_code CHAR(6) COMMENT '区代号',
    zip CHAR(6) COMMENT '邮政编码',
    address VARCHAR(50) COMMENT '详细地址',
    phone VARCHAR(20) COMMENT '手机',
    tel VARCHAR(20) COMMENT '固话',
    tag VARCHAR(10) COMMENT '地址类型',
    is_default INT(1) COMMENT '是否默认:0-非默认,1-默认',
    created_user VARCHAR(20) COMMENT '创建人',
    created_time DATETIME COMMENT '创建时间',
    modified_user VARCHAR(20) COMMENT '最后修改人',
    modified_time DATETIME COMMENT '最后修改时间',
    PRIMARY KEY (aid)
) DEFAULT CHARSET=utf8mb4;

27. 收货地址-创建实体类

cn.tedu.store.entity包中创建Address类,继承自BaseEntity类:

/**
 * 收货地址数据的实体类
 */
public class Address extends BaseEntity {

    private static final long serialVersionUID = 6788614546638401469L;

    private Integer aid;
    private Integer uid;
    private String receiver;
    private String provinceName;
    private String provinceCode;
    private String cityName;
    private String cityCode;
    private String areaName;
    private String areaCode;
    private String zip;
    private String address;
    private String phone;
    private String tel;
    private String tag;
    private Integer isDefault;

    // SET/GET/hashCode/equals/toString

}

28. 收货地址-某功能

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

饭九钦vlog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值