spring-boot集成七牛云实现图片上传与下载

文档 https://developer.qiniu.com/sdk#official-sdk

环境:spring-boot 2.5.1 七牛云sdk 7.7.0

前置条件

  • 注册七牛云账号
  • 创建对象存储空间
  • 如果空间是公开的,访问文件时,不需要认证,直接get文件url即可
  • 如果空间是私有的,访问文件时,需要进行认证

一般使用公开的空间,因为需要提供内容供用户访问。

开始集成

添加依赖

<dependency>
    <groupId>com.qiniu</groupId>
    <artifactId>qiniu-java-sdk</artifactId>
    <version>7.7.0</version>
</dependency>

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.6</version>
</dependency>

添加配置

oss:
  qiniu:
    domain: xxxxxa7om.hn-bkt.clouddn.com # 访问域名(默认使用七牛云测试域名)
    accessKey: XiAbXQnW1DgH-MC6QVXds_etJcLim4cPZ52xxxxx # 公钥
    secretKey: iZ2daBzj5XgmIX1rJjcgLUY0QMiqphxZk_9xxxxx # 私钥
    bucketName: blog-lyp  #存储空间名称

创建配置类,方便获取配置信息

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "oss.qiniu")
@Data
public class QiniuProperties
{
    private String domain; // CDN域名
    private String accessKey; // ACCESS_KEY
    private String secretKey; // SECRET_KEY
    private String bucketName; // 空间名称
}

创建TextUtils工具类,用于生成UUID格式的文件名称,或者从图片URL中提取Key

public class TextUtils
{
    // 根据文件名,生成UUID作为新的文件名
    public static String generateFileName(String filename)
    {
        Objects.requireNonNull(filename,"文件名为null");
        int index=filename.lastIndexOf('.');
        if(filename.isBlank() || index==-1)
        {
            throw new IllegalArgumentException("文件名不合法");
        }
        String suffix=filename.substring(index);
        String uuid= UUID.randomUUID().toString().replaceAll("-","");
        return uuid+suffix;
    }

    // 从图片URL中提取Key
    // http://quwf2a7om.hn-bkt.clouddn.com/xxx/11c85acc16f24361ba97999185fb0469.jpeg
    public static String getKey(String imageUrl)
    {
        if(imageUrl==null || imageUrl.trim().isEmpty())
        {
            return null;
        }
        return imageUrl.substring(imageUrl.indexOf(".com")+5);
    }
}

上传图片

创建上传表单,表单提交时,form必须设置属性 enctype="multipart/form-data"

创建七牛云Service接口

public interface QiniuService
{
    String uploadImage2qiniu(InputStream in,String key);
}

Service实现类

@Service
public class QiniuServiceImpl implements QiniuService
{
    private final String domain;
    private final String bucketName;

    // 七牛文件上传管理器
    private final Configuration cfg;
    private final Auth auth;

    @Autowired
    public QiniuServiceImpl(QiniuProperties oss)
    {
        String ak = oss.getAccessKey();
        String sk = oss.getSecretKey();
        this.domain = oss.getDomain(); // CDN域名
        this.bucketName = oss.getBucketName();

        // //构造一个带指定 Region 对象的配置类
        cfg = new Configuration(Region.huanan());
        auth = Auth.create(ak,sk);
    }

    /**
     * 上传图片到七牛云
     * @return 图片url
     * */
    @Override
    public String uploadImage2qiniu(InputStream in,String key)
    {
        try {
            UploadManager uploadManager = new UploadManager(cfg);
            // 根据命名空间生成的上传token
            String upToken = auth.uploadToken(bucketName);
            Response response = uploadManager.put(in,key,upToken,null, null);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            //System.out.println(putRet.key);
            //System.out.println(putRet.hash);
            return String.format("http://%s/%s",this.domain,putRet.key);
        } catch (QiniuException ex) {
            Response r = ex.response;
            System.err.println(r.toString());
            try {
                System.err.println(r.bodyString());
            } catch (QiniuException ex2) {
                //ignore
            }
        }
        return null;
    }
}

在Controller中调用Service中的方法,上传图片,成功后返回图片url

@Controller
public class QiniuController
{
    private final QiniuService qiniuService;

    @Autowired
    public QiniuController(QiniuService qiniuService)
    {
        this.qiniuService = qiniuService;
    }

    @PostMapping("/image/upload")
    @ResponseBody
    public String uploadImage(@RequestParam("file")MultipartFile file) throws IOException
    {
        if(!file.isEmpty())
        {
            InputStream in = file.getInputStream();
            String filename = file.getOriginalFilename();
            try
            {
                String key = "xxx/"+ TextUtils.generateFileName(filename);
                String imageUrl = qiniuService.uploadImage2qiniu(in,key);
                if(imageUrl!=null)
                {
                    return "上传成功: "+imageUrl;
                }
            }
            catch(IllegalArgumentException e)
            {
                e.printStackTrace();
            }
        }
        return "上传失败";
    }
}

下载图片

如果是公开空间的话,访问图片时,直接get上传图片时返回的url即可。

如果是私有空间的话,需要使用相关API,提供身份认证信息进行访问。具体参考文档。

删除图片

在Service接口中添加方法

boolean deleteImageFromQiniu(String key);

在Service实现类中

/**
    * 删除图片
    * */
@Override
public boolean deleteImageFromQiniu(String imageUrl)
{
    BucketManager bucketManager = new BucketManager(auth, cfg);
    try {
        String key=TextUtils.getKey(imageUrl);
        Response response = bucketManager.delete(bucketName,key);
        return response.isOK();
    } catch (QiniuException ex) {
        //如果遇到异常,说明删除失败
        System.err.println(ex.code());
        System.err.println(ex.response.toString());
    }
    return false;
}

然后,在Controller中,调用删除方法

@DeleteMapping("/image/delete")
@ResponseBody
public String deleteImage(@RequestParam("image")String imageUrl)
{
    boolean deleted = qiniuService.deleteImageFromQiniu(imageUrl);
    if(deleted)
    {
        return "删除成功";
    }
    return "删除失败";
}
posted @ 2021-07-05 17:45  lypzzzz  阅读(1117)  评论(0)    收藏  举报