基于策略模式实现文件上传



一、简介

策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。下面将演示如何使用策略模式实现文件上传到本地和腾讯云cos。

二、使用步骤

1.创建一个接口

首先创建一个文件上传策略接口,定义文件上传方法。

public interface UploadStrategy {
    /**
     * 上传文件到指定路径
     */
    String uploadFile(MultipartFile file, String path);
}

2.创建抽象模板类

创建一个抽象类,实现文件上传策略接口,拓展新的上传方式时,直接重写该抽象模板类即可,减少了代码量。

@Service
public abstract class AbstractUploadStrategy implements UploadStrategy {
    /**
     * 实现文件上传接口,配置文件名和上传路径
     */
    @Override
    public String uploadFile(MultipartFile file, String path) {
        try {
            // 生成文件名
            String md5 = FileUtils.getMd5(file);
            String extName = FileUtils.getExtension(file);
            String fileName = md5 + "." + extName;
            // 判断文件是否存在
            if (!exists(path + fileName)) {
                // 调用文件上传方法,由子类作具体实现
                upload(path, fileName, file.getInputStream());
            }
            // 返回文件访问路径
            return getFileAccessUrl(path + fileName);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("文件上传失败");
        }
    }

    /**
     * 判断文件是否存在
     */
    public abstract Boolean exists(String filePath);
    
    /**
     * 上传
     */
    public abstract void upload(String path, String fileName, InputStream inputStream) throws IOException;

    /**
     * 获取文件访问url
     */
    public abstract String getFileAccessUrl(String filePath);
}

3.重写抽象模板类

第一个实现类,文件上传到腾讯云cos

@Service("cosUploadStrategyImpl")
public class CosUploadStrategy extends AbstractUploadStrategy {
    @Autowired
    private CosProperties cosProperties;

    @Override
    public void upload(String path, String fileName, InputStream inputStream) {
        COSClient cosClient = getCosClient();
        try {
            ObjectMetadata objectMetadata = new ObjectMetadata();
            // 上传的流如果能够获取准确的流长度,则推荐一定填写 content-length
            objectMetadata.setContentLength(inputStream.available());
            // 调用cos方法上传
            cosClient.putObject(cosProperties.getBucketName(), path + fileName, inputStream, objectMetadata);
        } catch (CosServiceException e) {
            log.error("Error Message:" + e.getErrorMessage());
        } finally {
            cosClient.shutdown();
        }
    }

    @Override
    public Boolean exists(String filePath) {
        return getCosClient().doesObjectExist(cosProperties.getBucketName(), filePath);
    }

    @Override
    public String getFileAccessUrl(String filePath) {
        return cosProperties.getUrl() + filePath;
    }

    /**
     * 获取cosClient
     */
    private COSClient getCosClient() {
        // 1 初始化用户身份信息(secretId, secretKey)。
        COSCredentials cred = new BasicCOSCredentials(cosProperties.getSecretId(), cosProperties.getSecretKey());
        // 2 设置 bucket 的地域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
        Region region = new Region(cosProperties.getRegion());
        ClientConfig clientConfig = new ClientConfig(region);
        clientConfig.setHttpProtocol(HttpProtocol.https);
        // 3 生成 cos 客户端。
        return new COSClient(cred, clientConfig);
    }
}

第二个实现类,文件上传到本地

@Service("localUploadStrategyImpl")
public class LocalUploadStrategy extends AbstractUploadStrategy {
    /**
     * 本地路径
     */
    @Value("${upload.local.path}")
    private String localPath;

    /**
     * 访问url
     */
    @Value("${upload.local.url}")
    private String localUrl;

    @Override
    public Boolean exists(String filePath) {
        return new File(localPath + filePath).exists();
    }

    @Override
    public void upload(String path, String fileName, InputStream inputStream) throws IOException {
        // 判断目录是否存在
        File directory = new File(localPath + path);
        if (!directory.exists()) {
            //创建文件目录
            boolean isMkdir = directory.mkdirs();
            if (!isMkdir) {
                throw new ServiceException("创建目录失败");
            }
        }
        // 写入文件
        File file = new File(localPath + path + fileName);
        if (file.createNewFile()) {
            try (BufferedInputStream bis = new BufferedInputStream(inputStream);
                 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))) {
                byte[] bytes = new byte[4096];
                int length;
                while ((length = bis.read(bytes)) != -1) {
                    bos.write(bytes, 0, length);
                }
            }
        }
    }

    @Override
    public String getFileAccessUrl(String filePath) {
        return localUrl + filePath;
    }

}

4.创建context类

@Service
public class UploadStrategyContext {
    /**
     * yml文件中配置的上传模式,local,cos
     */
    @Value("${upload.strategy}")
    private String uploadMode;

    /**
     * key:上传上传策略名  value:上传策略
     * UploadStrategy接口有多个实现类,无法直接注入,这里采用用Map方式获取
     */
    @Autowired
    private Map<String, UploadStrategy> uploadStrategyMap;

    /**
     * 上传文件
     */
    public String executeUploadStrategy(MultipartFile file, String path) {
        //根据上传模式获取上传策略名
        String uploadStrategy= UploadModeEnum.getStrategy(uploadMode);
        //根据上传策略名获取上传策略
        UploadStrategy uploadStrategyImpl = uploadStrategyMap.get(uploadStrategy);
        //上传文件,并返回上传路径
        return uploadStrategyImpl.uploadFile(file,path);

    }
}

5.测试

调用文件上传方法,实现文件上传

@Autowired
private UploadStrategyContext uploadStrategyContext;
、、、
//调用文件上传方法
String url=uploadStrategyContext.executeUploadStrategy(file,path);

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值