Web项目实战 | 购物系统v2.0 | 开发记录(十)SpringBoot整合阿里云OSS对象存储服务 | Web将上传的商品图片保存到阿里云,同时将地址保存到数据库

——若发现文章内容有误,敬请指正,望不吝赐教,感谢!

文章目录

  • 以往记录
  • 运行环境
  • 一、OSS概述
  • 二、SpringBoot整合OSS(上传商品图片案例)
    • 2.1 导入Maven依赖
    • 2.2 通过类配置OSS
    • 2.3 编写OSS业务层代码
    • 2.4 编写控制层代码
    • 2.5 编写前端JQuery AJAX请求代码

以往记录


Web项目实战 | 购物系统v2.0 | 开发记录(一)需求分析 | 技术选型 | 系统设计 | 数据表设计 | SpringBoot、SSM、Thymeleaf、Bootstrap…

Web项目实战 | 购物系统v2.0 | 开发记录(二)搭建SpringBoot+SSM框架环境 | 配置Druid+MyBatis | 基于Bootstrap实现登陆页面| 图片验证码接口

Web项目实战 | 购物系统v2.0 | 开发记录(三)分页显示 | 根据商品名称进行模糊查询

Web项目实战 | 购物系统v2.0 | 开发记录(四)单个页面单个请求解决根据商品类型进行分页查询 | 使用省市区三级联动 | 使用JQuery 插件实现图片上传

Web项目实战 | 购物系统v2.0 | 开发记录(五)| 使用base64编码实现头像修改 | 用户个人信息修改 | JQuery动态提示

Web项目实战 | 购物系统v2.0 | 开发记录(六)商品详情页面 | 游客访问主页 | 运用Bootstrap4轻量级弹窗实现提示

Web项目实战 | 购物系统v2.0 | 开发记录(七)SpringBoot整合Shiro框架进行身份认证 | Shiro 加盐(MD5+Salt)验证登陆 | 数据表结构优化避免外键+设置中间表

Web项目实战 | 购物系统v2.0 | 开发记录(八)前后端分离初步思路 | JS处理URL参数实用函数 | AJAX 向后台传递Map类型数据 | MyBatis多表查询优化

Web项目实战 | 购物系统v2.0 | 开发记录(九)Controller层返回数据的封装 | 商品批量操作 | 五表联立实现商品搜索

运行环境


  • windows10
  • IDEA 2021.3 专业版
  • JDK8
  • SpringBoot2.6.x
  • JQuery 3.x
  • Druid 1.2.5
  • Bootstrap 4.6.0
  • MySQL 8
  • Navicat 15
  • OSS

一、OSS概述


官方文档:点击查看

OSS 全称 Object Storage Service,即对象存储服务,是由阿里云提供的海量、安全、低成本、高可靠的云存储服务。

OSS具有与平台无关的RESTful API接口,可在任意应用、任意地点存储与访问任何类型的数据。网站的图片、视频等文件就可以存放在OSS中(海量数据,交给阿里云平台维护,安全可靠)

更多内容,比如阿里云OSS服务的开通、配置、简单上传等可参考文章【点击查看】

二、SpringBoot整合OSS(上传商品图片案例)


注:整合前确保已经开通OSS服务

实现的最终效果:(前端的图片上传是使用的JQuery插件)

2.1 导入Maven依赖

pom.xml

        
        <dependency>
            <groupId>com.aliyun.ossgroupId>
            <artifactId>aliyun-sdk-ossartifactId>
            <version>3.13.2version>
        dependency>


        <dependency>
            <groupId>joda-timegroupId>
            <artifactId>joda-timeartifactId>
            <version>2.9.9version>
        dependency>

        <dependency>
            <groupId>org.apache.commonsgroupId>
            <artifactId>commons-lang3artifactId>
            <version>3.8.1version>
        dependency>

2.2 通过类配置OSS

查看OSS相关配置信息可通过以下步骤:

第一步,进入AccessKey管理
Web项目实战 | 购物系统v2.0 | 开发记录(十)SpringBoot整合阿里云OSS对象存储服务 | Web将上传的商品图片保存到阿里云,同时将地址保存到数据库_第1张图片
第二步,查看对应ID的Secret
Web项目实战 | 购物系统v2.0 | 开发记录(十)SpringBoot整合阿里云OSS对象存储服务 | Web将上传的商品图片保存到阿里云,同时将地址保存到数据库_第2张图片
第三步,查看Buncket的访问域名
Web项目实战 | 购物系统v2.0 | 开发记录(十)SpringBoot整合阿里云OSS对象存储服务 | Web将上传的商品图片保存到阿里云,同时将地址保存到数据库_第3张图片

ps:在使用时,也可通过用application声明键值对,由于没有提供起步依赖,所以需手动使用@Value注解注入

package com.uni.config;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import lombok.Data;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Data
@Configuration
public class AliyunConfig {
    private String endpoint = "oss-cn-hangzhou.aliyuncs.com";	// OSS服务的地域(这是杭州地区的,根据实际情况修改)
    private String accessKeyId = "自己的AccessKey ID";
    private String accessKeySecret = "自己的AccessKey Secret";
    private String bucketName = "uni1024";
    private String urlPrefix= "https://uni1024.oss-cn-hangzhou.aliyuncs.com/";	// 每个用户的OSS域名不同

    @Bean
    public OSS OSSClient() {
        return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    }
}

2.3 编写OSS业务层代码

FileUploadResult.java 实体类,用于返回前后端交互的返回值,笔者之前用的是RestResponse类,都差不多,这里主要为了和OSS区分开

package com.uni.pojo;

import lombok.Data;

// 前后端交互的返回值
@Data
public class FileUploadResult {
    // 文件唯一标识
    private String uid;
    // 文件名
    private String name;
    // 状态有:uploading done error removed
    private String status;
    // 服务端响应内容,如:'{"status": "success"}'
    private String response;
}

FileUploadService.java 实现文件上传的业务逻辑层

package com.uni.service;

import com.aliyun.oss.OSS;

import com.uni.config.AliyunConfig;
import com.uni.pojo.FileUploadResult;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;

import java.io.ByteArrayInputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class FileUploadService {
    // 允许上传的格式
    private static final String[] IMAGE_TYPE = new String[]{"bmp", "jpg",
            "jpeg", "gif", "png"};
    public final static String ERROR = "error";
    public final static String DONE = "done";
    public final static String SUCCESS = "success";
    @Autowired
    private OSS ossClient;
    @Autowired
    private AliyunConfig aliyunConfig;

    public FileUploadResult upload(String uploadFile, Long prodId) {

        Pattern pattern = Pattern.compile("image/(.*);");
        Matcher matcher = pattern.matcher(uploadFile);
        String uploadType = matcher.find() ? matcher.group(1) : null;
        // 校验图片格式
        boolean isLegal = false;
        for (String type : IMAGE_TYPE) {

            if (type.equals(uploadType)) {
                isLegal = true;
                break;
            }
        }
        //封装Result对象,并且将文件的byte数组放置到result对象中
        FileUploadResult fileUploadResult = new FileUploadResult();
        if (!isLegal) {
            fileUploadResult.setStatus(ERROR);
            return fileUploadResult;
        }
        //文件新路径
        String filePath = getFilePath(prodId, uploadType);
        // 上传到阿里云
        try {
            // 上传时需去掉base64编码的data:image/xxx;base64前缀
            ossClient.putObject(aliyunConfig.getBucketName(), filePath, new
                    ByteArrayInputStream(Base64Utils.decodeFromString(uploadFile.split(",")[1].trim())));
        } catch (Exception e) {
            e.printStackTrace();
            //上传失败
            fileUploadResult.setStatus(ERROR);
            return fileUploadResult;
        }
        fileUploadResult.setStatus(DONE);
        fileUploadResult.setResponse(SUCCESS);
        String fileUrl = this.aliyunConfig.getUrlPrefix() + filePath;
        fileUploadResult.setName(fileUrl);
        fileUploadResult.setUid(String.valueOf(System.currentTimeMillis()));
        return fileUploadResult;
    }

    private String getFilePath(Long prodId, String fileType) {
        DateTime dateTime = new DateTime();
        return "images/product/" + prodId + "/" + dateTime.toString("yyyy-MM-dd")
                + System.currentTimeMillis() + "." +
                fileType;
    }

}

2.4 编写控制层代码

控制层主要作用就是调用业务层的逻辑代码,调用完毕后将结果反馈给View视图。

@PostMapping("/update/{prodId}")
public String updateProdcutInfo(@PathVariable Long prodId, Product prod){
    // 图片单独处理
    Product oldProduct = productService.getProductWithProviderById(prodId);
    prod.setImg(oldProduct.getImg());
    // 执行修改业务
    int i = productService.modifyProductById(prod);
    return i == 2 ? RestResponse.ok("修改商品信息成功!").toJSONString()
            : RestResponse.fail("修改商品信息失败").toJSONString();
}

2.5 编写前端JQuery AJAX请求代码

笔者偷了个懒,这里直接将AJAX的代码嵌入到了插件的函数里,主要部分就在$.ajax

//裁剪后的处理: 修改商品图片
$("#sureCut").on("click",function () {
    if ($("#tailoringImg").attr("src") == null ){
        return false;
    }else{
        let cas = $('#tailoringImg').cropper('getCroppedCanvas');//获取被裁剪后的canvas
        let base64url = cas.toDataURL('image/png'); //转换为base64地址形式
        $("#finalImg").prop("src",base64url);//显示为图片的形式
        $.ajax({
            url: '/admin/product/update/' + $('#form-id').val(),
            type: 'PUT',
            data: {base64url:base64url},
            dataType: 'JSON',
            error: (err) =>{ alert('修改头像请求失败.'); console.error(err.responseText);},
            success: (data) => {
                open_toast(data['code'] === 1 ? 'success' : 'fail', data['message'])}
        })

        //关闭裁剪框
        closeTailor();
    }
});

至此,SpringBoot整合OSS的简单应用就结束了。

你可能感兴趣的:(项目实战2:,spring,boot,前端,阿里云)