七牛云基于java-sdk封装

98 阅读7分钟

调用测试

package com.example.honyee;

import com.example.honyee.qiniu.QiniuUtils;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
/**
 * 测试
 * @author honyee
 */
public class QiniuTest {
    // 需要斜杠结尾
    static String rootPath = "C:\\Users\\Lenovo\\Desktop\\xiuxian-data-station\\xiuxian-v3.5\\";

    public static void main(String[] args) throws IOException {
        upload(new File(rootPath));
    }

    /**
     * 批量上传
     * @param file 文件or目录
     */
    public static void upload(File file) throws IOException {
        if (file == null || !file.exists()) {
            return;
        }
        if (file.isFile()) {
            byte[] bytes = Files.readAllBytes(Path.of(file.getPath()));
            // windows分隔符
            String key = file.getAbsolutePath().replace(rootPath, "").replaceAll("\\\\","/");
            String resKey = QiniuUtils.uploadImage(bytes, key);
            System.out.println(key);
        } else {
            for (File child : Optional.ofNullable(file.listFiles()).orElse(new File[]{})) {
                upload(child);
            }
        }
    }

}


目录结构

image.png

maven

    <dependency>
      <groupId>com.qiniu</groupId>
      <artifactId>qiniu-java-sdk</artifactId>
      <version>[7.7.0, 7.10.99]</version>
    </dependency>

工具封装

QiniuUtils

package com.example.honyee.qiniu;

import com.example.honyee.qiniu.base.QiniuAuditCallbackV2;
import com.example.honyee.qiniu.base.QiniuBase;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qiniu.storage.Region;
import com.qiniu.util.Auth;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;

public class QiniuUtils {
    private static final Logger logger = LoggerFactory.getLogger(QiniuUtils.class);

    public static final String AK = "VQlK3dF5dbJwxrMH04DHXt6A9Gt5LmChYimT_1Vb";

    public static final String SK = "rXxxXElw15v2eeDzFhIvw2zEhpOF0gcT6wXMv8uD";

    public static final String BUCKET_NAME = "lanren-station";

    // 绑定的域名
    public static final String BASE_URL = "";

    // bucket所在的地区
    public static final Region REGION = Region.regionCnEast2();

    public static final Auth AUTH = Auth.create(AK, SK);
    
    /**
     * 图片资源的上传token
     */
    public static String getUpToken() {
        return AUTH.uploadToken(BUCKET_NAME);
    }

    /**
     * 上传图片
     *
     * @param file 文件
     * @param key  默认不指定key的情况下,以文件内容的hash值作为文件名
     * @return 七牛图片查询依据 (key有值时,返回key,无值时,返回文件hash值)
     */
    public static String uploadImage(MultipartFile file, String key) {
        try {
            return QiniuBase.uploadImage(file.getBytes(), key, getUpToken(), REGION);
        } catch (IOException e) {
            logger.info("七牛图片上传失败,IO错误{}", e.getMessage());
        }
        return null;
    }

    public static String uploadImage(byte[] bytes, String key) {
        return QiniuBase.uploadImage(bytes, key, getUpToken(), REGION);
    }

    public static String uploadImage(byte[] bytes, String type, String userId, String key) {
        return uploadImage(bytes, String.format("%s/%s/%s", type, userId, key));
    }

    public static String uploadImage(MultipartFile file, String type, String userId, String key) {
        return uploadImage(file, String.format("%s/%s/%s", type, userId, key));
    }

    public static boolean deleteImage(String key) {
        return QiniuBase.deleteImage(key, BUCKET_NAME, REGION, AUTH);
    }

    public static boolean exists(String key) {
        // 剔除第一个斜杠
        if (key.charAt(0) == '/') {
            key = key.substring(1);
        }
        return QiniuBase.exists(key, BUCKET_NAME, REGION, AUTH);
    }

    /**
     * 刷新
     *
     * @param filePath 文件路径,例如  /xxx/yyy.png
     */
    public static boolean refresh(String filePath) {
        return QiniuBase.refresh(BASE_URL + filePath, AUTH);
    }

    /**
     * 通过文件名,获取图片审核结果
     *
     * @param imageName 七牛存储里的文件名
     * @return true 属于色情, false 正常图,或处理失败
     */
    public static boolean auditImageYellow(String imageName) throws JsonProcessingException {
        if(imageName == null){
            return false;
        }
        String url = BASE_URL + imageName;
        String result = QiniuBase.imgAuditYellow(AUTH, url);
        QiniuAuditCallbackV2 callbackV2 = new ObjectMapper().readValue(result, QiniuAuditCallbackV2.class);
        if(callbackV2 != null && callbackV2.isAuditPass()) {
            return callbackV2.isBlock();
        }
        logger.error("鉴黄异常:{}", result);
        return false;
    }

    /**
     * 通过文件名,获取图片审核结果
     *
     * @param imageName 七牛存储里的文件名
     * @return true 属于广告或者疑似, false 正常图,或处理失败
     */
    public static boolean auditImageAdvertisement(String imageName) throws JsonProcessingException {
        if (imageName == null) {
            return false;
        }
        String url = BASE_URL + imageName;
        String result = QiniuBase.imgAuditAdvertisement(AUTH, url);
        QiniuAuditCallbackV2 callbackV2 = new ObjectMapper().readValue(result, QiniuAuditCallbackV2.class);
        if (callbackV2 != null && callbackV2.isAuditPass()) {
            boolean b = callbackV2.isBlock() || callbackV2.isReview();
            if (b) {
                logger.error("广告图片:{}", imageName);
            }
            return b;
        }
        logger.error("鉴黄异常:{}", result);
        return false;
    }

    /**
     * 上传图片并审核
     *
     * @param file 文件
     * @param key 默认不指定key的情况下,以文件内容的hash值作为文件名
     * @return true 违规, false 正常图,或处理失败
     */
    public static boolean uploadWithAudit(MultipartFile file,String key) throws JsonProcessingException {
        String fileName = uploadImage(file, key);
        return audit(fileName);
    }

    /**
     * 审核
     * @return true 属于色情或者广告, false 正常图,或处理失败
     */
    public static boolean audit(String fileName) throws JsonProcessingException {
        return auditImageYellow(fileName) || auditImageAdvertisement(fileName);
    }

    /**
     * 上传图片并审核
     *
     * @param fileBytes 文件字节流
     * @param key       默认不指定key的情况下,以文件内容的hash值作为文件名
     * @return true 属于色情, false 正常图,或处理失败
     */
    public static boolean uploadWithAudit(byte[] fileBytes,String key) throws JsonProcessingException {
        return auditImageYellow(uploadImage(fileBytes, key));
    }
}

QiniuBase

package com.example.honyee.qiniu.base;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qiniu.cdn.CdnManager;
import com.qiniu.cdn.CdnResult;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Client;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;

/**
 * @author honyee
 */
public class QiniuBase {
    private static final Logger logger = LoggerFactory.getLogger(QiniuBase.class);

    public static final String AUDIT_PARAM = "?qpulp";

    /**
     * 上传图片
     *
     * @param uploadBytes 文件字节流
     * @param key         默认不指定key的情况下,以文件内容的hash值作为文件名
     * @return 七牛图片查询依据 (key有值时,返回key,无值时,返回文件hash值)
     */
    public static String uploadImage(byte[] uploadBytes, String key, String upToken, Region region) {
        //构造一个带指定 Region 对象的配置类 不同区域的空间,需要对应 不同 region
        /*
        机房	Region
        华东	Region.region0(), Region.huadong()
        华北	Region.region1(), Region.huabei()
        华南	Region.region2(), Region.huanan()
        北美	Region.regionNa0(), Region.beimei()
        东南亚	Region.regionAs0(), Region.xinjiapo()
        * */
        Configuration cfg = new Configuration(region);
        //...其他参数参考类注释
        UploadManager uploadManager = new UploadManager(cfg);

        try {
            // 剔除第一个斜杠
            if (key.charAt(0) == '/') {
                key = key.substring(1);
            }
            ByteArrayInputStream byteInputStream = new ByteArrayInputStream(uploadBytes);
            Response response = uploadManager.put(byteInputStream, key, upToken, null, null);
            //解析上传成功的结果
            DefaultPutRet putRet = new ObjectMapper().readValue(response.bodyString(), DefaultPutRet.class);
            //System.out.println(putRet.key);
            //System.out.println(putRet.hash);
            return putRet.key;
        } catch (QiniuException ex) {
            Response r = ex.response;
            logger.info("七牛图片上传错误,{}", r.toString());
            try {
                logger.info("七牛图片上传错误,{}", r.bodyString());
            } catch (QiniuException ex2) {
                //ignore
            }
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        return key;
    }

    /**
     * 删除图片
     *
     * @param key    文件名
     * @param bucket bucket名
     * @param region 区域
     * @return 结果
     */
    public static boolean deleteImage(String key, String bucket, Region region, Auth auth) {
        Configuration cfg = new Configuration(region);
        //...其他参数参考类注释
        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            // 剔除第一个斜杠
            if (key.charAt(0) == '/') {
                key = key.substring(1);
            }
            bucketManager.delete(bucket, key);
        } catch (QiniuException ex) {
            //如果遇到异常,说明删除失败
            logger.info(ex.code() + "");
            logger.info(ex.response.toString());
            return false;
        }

        return true;

    }

    public static boolean exists(String key, String bucket, Region region, Auth auth) {
        Configuration cfg = new Configuration(region);
        //...其他参数参考类注释
        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            // 剔除第一个斜杠
            if (key.charAt(0) == '/') {
                key = key.substring(1);
            }
            bucketManager.stat(bucket, key);
        } catch (QiniuException ex) {
            //如果遇到异常,说明文件不存在
            //logger.info(ex.code() + "");
            //logger.info(ex.response.toString());
            return false;
        }
        return true;
    }

    /**
     * 刷新图片
     *
     * @param url 完整路径
     */
    public static boolean refresh(String url, Auth auth) {
        CdnManager c = new CdnManager(auth);
        //待刷新的链接列表
        String[] urls = new String[]{
                url
        };
        try {
            //单次方法调用刷新的链接不可以超过100个
            CdnResult.RefreshResult result = c.refreshUrls(urls);
            System.out.println(result.code);
            //获取其他的回复内容
        } catch (QiniuException e) {
            System.err.println(e.response.toString());
            return false;
        }

        return true;
    }

    /**
     * 7牛V3图片监黄 <Br>
     * https://developer.qiniu.com/censor/api/5588/image-censor
     * <p>
     * scenes 鉴定类型
     * pulp 图片鉴黄
     * <p>
     * label/group 鉴定结果标签
     * normal:正常图片,无色情内容
     * sexy:性感图片
     * pulp:色情图片
     * <p>
     * suggestion 审核结果
     * block:表示系统确认审核内容违规,建议您将其删除。
     * review:表示系统无法确认审核内容是否违规,建议您进行人工复核。
     * pass:表示系统确认审核内容正常,建议您忽略该文件。
     *
     * @param url 完整路径
     */
    public static String imgAuditYellow(Auth auth, String url) {
        String requestUrl = "http://ai.qiniuapi.com/v3/image/censor";
        String host = "ai.qiniuapi.com";
        String body = "{ \"data\": { \"uri\": \"" + url + "\" }, \"params\": { \"scenes\": [ \"pulp\" ] } }";
        String contentType = "application/json";
        String method = "POST";

        // 构造七牛鉴权签名  https://developer.qiniu.com/kodo/kb/3702/QiniuToken
        String qiniuToken = "Qiniu " + auth.signRequestV2(requestUrl, method, body.getBytes(), contentType);

        StringMap header = new StringMap();
        header.put("Host", host);
        header.put("Authorization", qiniuToken);
        header.put("Content-Type", contentType);
        Configuration cfg = new Configuration(Region.autoRegion());
        Client client = new Client(cfg);
        Response response = null;
        try {
            response = client.post(requestUrl, body.getBytes(), header, contentType);
            return response.bodyString();
        } catch (QiniuException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String imgAuditAdvertisement(Auth auth, String url) {
        String requestUrl = "http://ai.qiniuapi.com/v3/image/censor";
        String host = "ai.qiniuapi.com";
        String body = "{ \"data\": { \"uri\": \"" + url + "\" }, \"params\": { \"scenes\": [ \"ads\" ] } }";
        String contentType = "application/json";
        String method = "POST";

        // 构造七牛鉴权签名  https://developer.qiniu.com/kodo/kb/3702/QiniuToken
        String qiniuToken = "Qiniu " + auth.signRequestV2(requestUrl, method, body.getBytes(), contentType);

        StringMap header = new StringMap();
        header.put("Host", host);
        header.put("Authorization", qiniuToken);
        header.put("Content-Type", contentType);
        Configuration cfg = new Configuration(Region.autoRegion());
        Client client = new Client(cfg);
        Response response = null;
        try {
            response = client.post(requestUrl, body.getBytes(), header, contentType);
            return response.bodyString();
        } catch (QiniuException e) {
            e.printStackTrace();
            return null;
        }
    }
}

DTO

package com.example.honyee.qiniu.base;

/**
 *  七牛云鉴黄结果
 */
public class QiniuAuditResult {
    /**
     * 介于0-2间的整数,表示该图像被判定为哪个分类,分别对应: 0色情;1性感;2正常,三种分类的具体解释如下:
     * 0色情:有明显的敏感部分裸露的图片,血腥图片,描述性交行为的体位或姿势和色情场景的图片。注意,儿童色情的内容,也被归为0
     * 1性感:衣着暴露但没有裸露敏感部位。次类跨度比较大,从露出皮肤较多的图片到性感写真、诱惑自拍等,区分0和1最重要的规则为是否有裸露敏感部位。注意,孕妇自拍露肚子的图也被归为了1
     * 2正常:非色情,非性感图片
     *
     */
    private Integer label;
    /**
     * 是否需要人工复审该图片。true需要false不需要
     */
    private Float score;
    /**
     * 表示该图像被识别为某个分类的概率值,概率越高、机器越肯定;您可以根据您的需求确定需要人工复审的界限
     */
    private Boolean review;

    public Integer getLabel() {
        return label;
    }

    public void setLabel(Integer label) {
        this.label = label;
    }

    public Float getScore() {
        return score;
    }

    public void setScore(Float score) {
        this.score = score;
    }

    public Boolean getReview() {
        return review;
    }

    public void setReview(Boolean review) {
        this.review = review;
    }
}

package com.example.honyee.qiniu.base;

import java.util.Map;

/**
 *  七牛云鉴黄结果
 */
public class QiniuAuditResultV2 {
    /**
     * suggestion 审核结果
     *      block:表示系统确认审核内容违规,建议您将其删除。
     *      review:表示系统无法确认审核内容是否违规,建议您进行人工复核。
     *      pass:表示系统确认审核内容正常,建议您忽略该文件。
     */
    private String suggestion;
    /**
     * scenes 鉴定类型
     *      pulp 图片鉴黄
     *          label/group 鉴定结果标签
     *          normal:正常图片,无色情内容
     *          sexy:性感图片
     *          pulp:色情图片
     */
    private Map<String,Object> scenes;

    public String getSuggestion() {
        return suggestion;
    }

    public void setSuggestion(String suggestion) {
        this.suggestion = suggestion;
    }

    public Map<String, Object> getScenes() {
        return scenes;
    }

    public void setScenes(Map<String, Object> scenes) {
        this.scenes = scenes;
    }
}

package com.example.honyee.qiniu.base;

/**
 * 七牛云鉴黄反馈
 */
public class QiniuAuditCallback {
    /**
     * 处理状态:0调用成功
     */
    private Integer code;

    private String name;
    /**
     * 与code对应的状态描述信息
     */
    private String message;
    /**
     * 处理结果
     */
    private QiniuAuditResult result;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public QiniuAuditResult getResult() {
        return result;
    }

    public void setResult(QiniuAuditResult result) {
        this.result = result;
    }

    public Boolean isAuditPass(){
        return 0 == code;
    }

    /**
     * 是否属于色情
     */
    public Boolean belongSeqing(){
        return this.result.getLabel() == 0;
    }
}

package com.example.honyee.qiniu.base;

import java.util.Objects;

/**
 * 七牛云鉴黄反馈
 */
public class QiniuAuditCallbackV2 {
    /**
     * 处理状态:0调用成功
     */
    private Integer code;

    /**
     * 与code对应的状态描述信息
     */
    private String message;
    /**
     * 处理结果
     */
    private QiniuAuditResultV2 result;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public QiniuAuditResultV2 getResult() {
        return result;
    }

    public void setResult(QiniuAuditResultV2 result) {
        this.result = result;
    }

    public boolean isAuditPass(){
        return Objects.equals(200,code);
    }

    /**
     * 是否违规
     */
    public Boolean isBlock(){
        return "block".equals(this.result.getSuggestion());
    }
    /**
     * 是否疑似
     */
    public Boolean isReview(){
        return "review".equals(this.result.getSuggestion());
    }
}