Java实现上传网络图片到七牛云存储详解

前言

最近阳了,第二条杠红的发紫,真难受啊,但是吧,博客上有个bug,不解决感觉比阳了还难受。

话还是要从博客的图片显示不出来这里说起,当时做的时候,在发文章这里,感觉没有封面的话,文章会很孤单,所以就设计了个封面这块儿。但是,封面如果太邋遢也还不如没有。

所以我就从网上的一个接口里面随机取的一些精美图片,本来好好的,结果今天一看,那个接口报错403了,当时就想着,这样做太依赖别人了,什么东西都得掌控在自己手里,不然出问题了难受的还是自己。

正好借这个机会,就重新设计了下,先从接口中取,如果接口中的图片能看,则用这个图片,顺便将这个图片传至七牛云存储中,否则就随机从七牛云存储中指定些图片展示出来,这样就不会受制于人。

效果图

Java实现上传网络图片到七牛云存储详解

直接将图片传至七牛云中,给我们返回该图片的地址。

代码实现

因为七牛云上传图片的时候,传递的是MultipartFile类型,所以我们需要将网络图片utl转换成流,然后在转换成MultipartFile,接着使用七牛云提供的方法上传即可。

下面我们先看看怎么将网络url转换成MultipartFile,这个代码网上很多,大家可以随便搜一个放上来就行,我这边封装了个工具类:FilesUtil

package com.shiyi.util;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import org.apache.http.entity.ContentType;
import org.apache.pdfbox.io.IOUtils;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * @author: muxiongxiong
 * @date: 2022年12月29日 15:35
 * 博客:https://blog.csdn.net/qq_34137397
 * 个人站:https://www.穆雄雄.com
 * 个人站:https://www.muxiongxiong.cn
 * @Description: 类的描述
 */
public class FilesUtil {


    /**
     * 根据地址获得数据的输入流
     *
     * @param strUrl 网络连接地址
     * @return url的输入流
     */
    public static InputStream getInputStreamByUrl(String strUrl) {
        HttpURLConnection conn = null;
        try {
            URL url = new URL(strUrl);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(20 * 1000);
            final ByteArrayOutputStream output = new ByteArrayOutputStream();
            IOUtils.copy(conn.getInputStream(), output);
            return new ByteArrayInputStream(output.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (conn != null) {
                    conn.disconnect();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 将网络地址转换成MultipartFile
     * @param strUrl
     * @return
     */
    public static MultipartFile onlineAddressTransferFile(String strUrl){
        MultipartFile file = null;
        try {
            String fileName = strUrl.substring(strUrl.lastIndexOf("/") + 1);
            InputStream  stream = getInputStreamByUrl(strUrl);
            if (!ObjectUtils.isEmpty(stream)) {
                 file = new MockMultipartFile(fileName, fileName, "", stream);
                return file;
            }
        }catch (Exception exception){
            exception.printStackTrace();
        }
        return file;
    }

}

在调用的时候我们这样调:

  /**
     * 手动上传网络图片
     */
    @GetMapping(value = "/uploadFm")
    public ResponseResult uploadFm(){
        MultipartFile multipartFile =  FilesUtil.onlineAddressTransferFile("https://img-community.csdnimg.cn/images/86f32eac875e42af9ed9e91b809dc7d8.png");
        return cloudOssService.upload(multipartFile);
    }

剩下的就是七牛云里面的方法了,这边一起放上来吧:

CloudOssService接口代码:

package com.shiyi.service;

import com.shiyi.common.ResponseResult;
import org.springframework.web.multipart.MultipartFile;

public interface CloudOssService {
    /**
     * 上传
     * @param file 文件
     * @return
     */
    ResponseResult upload(MultipartFile file);

    /**
     * 批量删除文件
     * @param key 文件名
     * @return
     */
    ResponseResult delBatchFile(String ...key);
}

CloudOssServiceImpl实现类,主要是实现CloudOssService接口的:

package com.shiyi.service.impl;


import com.shiyi.common.ResponseResult;

import com.shiyi.enums.FileUploadModelEnum;
import com.shiyi.service.CloudOssService;
import com.shiyi.service.SystemConfigService;
import com.shiyi.strategy.context.FileUploadStrategyContext;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.Objects;

@Service
@RequiredArgsConstructor
public class CloudOssServiceImpl implements CloudOssService {

    private final SystemConfigService systemConfigService;

    private final FileUploadStrategyContext fileUploadStrategyContext;

    private String strategy;

    /**
     * 上传文件
     * @param file
     * @return
     */
    @Override
    public ResponseResult upload(MultipartFile file) {
        if (file.getSize() > 1024 * 1024 * 10) {
            return ResponseResult.error("文件大小不能大于10M");
        }
        //获取文件后缀
        String suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf(".") + 1);
        if (!"jpg,jpeg,gif,png".toUpperCase().contains(suffix.toUpperCase())) {
            return ResponseResult.error("请选择jpg,jpeg,gif,png格式的图片");
        }
        getFileUploadWay();
        String key = fileUploadStrategyContext.executeFileUploadStrategy(strategy, file, suffix);
        return ResponseResult.success(key);
    }


    /**
     * 删除文件
     * @param key
     * @return
     */
    @Override
    public ResponseResult delBatchFile(String ...key) {
        getFileUploadWay();
        Boolean isSuccess = fileUploadStrategyContext.executeDeleteFileStrategy(strategy, key);
        if (!isSuccess) {
            return ResponseResult.error("删除文件失败");
        }
        return ResponseResult.success();
    }

    private void getFileUploadWay() {
        strategy = FileUploadModelEnum.getStrategy(systemConfigService.getCustomizeOne().getFileUploadWay());
    }
}

最后是文件上传策略上下文类:

package com.shiyi.strategy.context;

import com.shiyi.strategy.FileUploadStrategy;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.Map;


/**
 * @apiNote 文件上传策略上下文
 */
@Service
@RequiredArgsConstructor
public class FileUploadStrategyContext {

    private final Map<String, FileUploadStrategy> fileUploadStrategyMap;

    /**
     * 执行文件上传策略
     *
     * @param file 文件对象
     * @return {@link String} 文件名
     */
    public String executeFileUploadStrategy(String fileUploadMode, MultipartFile file,String suffix) {
         return fileUploadStrategyMap.get(fileUploadMode).fileUpload(file,suffix);
    }

    /**
     * 删除文件策略
     * @param fileUploadMode
     * @param key
     * @return
     */
    public Boolean executeDeleteFileStrategy(String fileUploadMode,String ...key) {
         return fileUploadStrategyMap.get(fileUploadMode).deleteFile(key);
    }
}

QiNiuUploadStrategyImpl实现类的代码:

package com.shiyi.strategy.imp;

import com.alibaba.fastjson.JSON;
import com.qiniu.common.QiniuException;
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.BatchStatus;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.util.Auth;
import com.shiyi.entity.SystemConfig;
import com.shiyi.enums.QiNiuAreaEnum;
import com.shiyi.service.SystemConfigService;
import com.shiyi.strategy.FileUploadStrategy;
import com.shiyi.util.UUIDUtils;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;


@Service("qiNiuUploadStrategyImpl")
@RequiredArgsConstructor
public class QiNiuUploadStrategyImpl implements FileUploadStrategy {

    private final Logger logger = LoggerFactory.getLogger(QiNiuUploadStrategyImpl.class);

    private final SystemConfigService systemConfigService;
    private String qi_niu_accessKey;
    private String qi_niu_secretKey;
    private String qi_niu_bucket;
    private Region region;
    private String qi_niu_url;

    @PostConstruct
    private void init(){
        SystemConfig systemConfig = systemConfigService.getCustomizeOne();
        qi_niu_accessKey = systemConfig.getQiNiuAccessKey();
        qi_niu_secretKey = systemConfig.getQiNiuSecretKey();
        qi_niu_bucket = systemConfig.getQiNiuBucket();
        qi_niu_url = systemConfig.getQiNiuPictureBaseUrl();
        region = QiNiuAreaEnum.getRegion(systemConfig.getQiNiuArea());
    }

    public void list() {
        Configuration configuration = new Configuration(region);
        Auth auth = Auth.create(qi_niu_accessKey, qi_niu_secretKey);
        BucketManager bucketManager = new BucketManager(auth,configuration);
        BucketManager.FileListIterator fileListIterator = bucketManager.createFileListIterator(qi_niu_bucket, null, 1000, null);
        while (fileListIterator.hasNext()) {
            FileInfo[] next = fileListIterator.next();
            for (FileInfo fileInfo : next) {
                logger.info("文件打印开始,文件名:{}",qi_niu_url + fileInfo.key);
                logger.info("文件类别打印开始,类别:{}",fileInfo.mimeType);
                logger.info("文件大小打印开始,大小:{}",fileInfo.fsize);
            }
        }
    }

    /**
     * 七牛云文件上传
     * @param file 文件
     * @param suffix 后缀
     * @return
     */
    @Override
    public String fileUpload(MultipartFile file,String suffix) {
        String key = null;
        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(region);
        //...其他参数参考类注释
        UploadManager uploadManager = new UploadManager(cfg);
        //...生成上传凭证,然后准备上传
        Auth auth = Auth.create(qi_niu_accessKey, qi_niu_secretKey);
        String upToken = auth.uploadToken(qi_niu_bucket);
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
            //这里需要处理一下,不能让每次上去都是个UUID的文件名
            Response response = uploadManager.put(inputStream, "blog/"+UUIDUtils.getUuid() + "." + suffix, upToken,null,null);
            //解析上传成功的结果
            DefaultPutRet putRet = JSON.parseObject(response.bodyString(),DefaultPutRet.class);
            key =  qi_niu_url + putRet.key;
        } catch (QiniuException ex) {
            Response r = ex.response;
            logger.error("QiniuException:{}",r.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return key;
    }

    /**
     * 批量删除文件
     * @return
     */
    @Override
    public Boolean deleteFile(String ...keys) {
        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(Region.region2());
        //...其他参数参考类注释
        Auth auth = Auth.create(qi_niu_accessKey, qi_niu_secretKey);
        BucketManager bucketManager = new BucketManager(auth, cfg);
        try {
            BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();
            batchOperations.addDeleteOp(qi_niu_bucket, keys);
            Response response = bucketManager.batch(batchOperations);
            BatchStatus[] batchStatusList = response.jsonToObject(BatchStatus[].class);
            for (int i = 0; i < keys.length; i++) {
                BatchStatus status = batchStatusList[i];
                String key = keys[i];
                System.out.print(key + "\t");
                if (status.code == 200) {
                    System.out.println("delete success");
                } else {
                    System.out.println(status.data.error);
                }
            }
            return true;
        } catch (QiniuException ex) {
            System.err.println(ex.response.toString());
            return false;
        }
    }

}

然后我们从接口里面直接调用即可上传上去。

Java实现上传网络图片到七牛云存储详解

原文地址:https://blog.csdn.net/qq_34137397/article/details/128486411