用策略模式做文件上传

SpringBoot2.1.x,okhttp3网络请求之MultipartFile方式上传文件,multipart/form-data表单多文件+多参数 一)引入okhttp3的jar <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.0.0</version> </dependency> 二)提供一个上传服务接口,文件类型为MultipartFile package com.oyse. 阅读详情

文件策略接口


/**
 * 文件策略接口
 */
public interface FileStrategy {
    /**
     * 文件上传
     *
     * @param file    文件
     * @param bucket  桶
     * @param bizType 业务类型
     * @return 文件对象
     */
    File upload(MultipartFile file, String bucket, String bizType);

    /**
     * 删除源文件
     *
     * @param fileDeleteBO 待删除文件
     * @return 是否成功
     */
    boolean delete(FileDeleteBO fileDeleteBO);
}

多种实现类
在这里插入图片描述

文件抽象策略 处理类

/**
 * 文件抽象策略 处理类
 *
 */
@Slf4j
@RequiredArgsConstructor
public abstract class AbstractFileStrategy implements FileStrategy {

    //    public static final String CF_ACCOUNT_ID = "842c4ed8bb33981a8b1c6ee70557a796";
    String CF_ACCOUNT_ID;
    public static final String CF_BASE_URL = "https://api.cloudflare.com/client/v4/accounts/";
    private static final String FILE_SPLIT = ".";
    protected final FileServerProperties fileProperties;
    protected final FileMapper fileMapper;

    /**
     * 上传文件
     *
     * @param multipartFile 文件
     * @return 附件
     */
    @Override
    public File upload(MultipartFile multipartFile, String bucket, String bizType) {
        try {
            if (!StrUtil.contains(multipartFile.getOriginalFilename(), FILE_SPLIT)) {
                throw BizException.wrap(BASE_VALID_PARAM.build("文件缺少后缀名"));
            }

            File file = File.builder()
                    .originalFileName(multipartFile.getOriginalFilename())
                    .contentType(multipartFile.getContentType())
                    .size(multipartFile.getSize())
                    .bizType(bizType)
                    .suffix(FilenameUtils.getExtension(multipartFile.getOriginalFilename()))
                    .fileType(FileTypeUtil.getFileType(multipartFile.getContentType()))
                    .build();
            if (multipartFile.getContentType().startsWith("vtt")) {
                uploadVtt(file, multipartFile, bucket, bizType);
            } else {
                uploadFile(file, multipartFile, bucket);
            }
            return file;
        } catch (Exception e) {
            log.error("ex", e);
            throw BizException.wrap(BASE_VALID_PARAM.build("文件上传失败"), e);
        }
    }

    /**
     * @param uid         uid
     * @param languageTag languageTag
     * @throws Exception
     */
    private void uploadVtt(File file, MultipartFile multipartFile, String uid, String languageTag) throws Exception {
        String contentType = file.getContentType();
        String url = CF_BASE_URL + CF_ACCOUNT_ID + "/stream/" + uid + "/" + languageTag;

        OkHttpClient client = new OkHttpClient();
        Request request = getRequest(multipartFile, contentType, url);
        extracted(client, request);
        final Call call = client.newCall(request);
        try (Response response = call.execute();) {
            assert response.body() != null;
            String string = response.body().string();
            CloudFlareResult<Map<String, Object>> cloudFlareResult = JSONObject.parseObject(string, new TypeReference<CloudFlareResult<Map<String, Object>>>() {
            });
            if (!cloudFlareResult.getSuccess()) {
                throw new BizException("uploadFile fail");
            }
//            CloudFlareVideoResult result = cloudFlareResult.getResult();
//            file.setUrl(result.getPlayback().getOrDefault("hls", "")).setUniqueFileName(result.getThumbnail());
        } catch (Exception e) {
            log.error("uploadFile fail:{}", e.getMessage(), e);
            throw new BizException("uploadFile fail");
        }
    }

    @NotNull
    private static Request getRequest(MultipartFile multipartFile, String contentType, String url) throws IOException {
        RequestBody fileBody = RequestBody.create(MediaType.parse(contentType), multipartFile.getBytes());
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", multipartFile.getName(), fileBody)
                .build();
        Request request = new Request.Builder().url(url).addHeader("Authorization", "Bearer KOs2DOm2w0_QvlYizgkVjso5HOQxnr-krRTfIVVd").post(requestBody).build();
        return request;
    }

    private static void extracted(OkHttpClient client, Request request) {
        client.newBuilder()
                .connectTimeout(500, TimeUnit.SECONDS)
                .readTimeout(500, TimeUnit.SECONDS)
                .callTimeout(500, TimeUnit.SECONDS)
                .writeTimeout(500, TimeUnit.SECONDS)
                .build()
                .newCall(request);
    }

    /**
     * 具体类型执行上传操作
     *
     * @param file          附件
     * @param multipartFile 文件
     * @param bucket        bucket
     * @throws Exception 异常
     */
    protected abstract void uploadFile(File file, MultipartFile multipartFile, String bucket) throws Exception;

    @Override
    public String getUrl(FileGetUrlBO fileGet) {
        return findUrl(Arrays.asList(fileGet)).get(fileGet.getPath());
    }

    /**
     * 获取年月日 2020/09/01
     *
     * @return
     */
    protected String getDateFolder() {
        return LocalDate.now().format(DateTimeFormatter.ofPattern(SLASH_DATE_FORMAT));
    }

    /**
     * 企业/年/月/日/业务类型/唯一文件名
     */
    protected String getPath(String bizType, String uniqueFileName) {
        return new StringJoiner(StrPool.SLASH).add(String.valueOf(ContextUtil.getTenant()))
                .add(bizType).add(getDateFolder()).add(uniqueFileName).toString();
    }

    protected String getUniqueFileName(File file) {
        return new StringJoiner(StrPool.DOT)
                .add(UUID.randomUUID().toString().replace("-", ""))
                .add(file.getSuffix()).toString();
    }
}

HUAWEI_OSS 文件上传的实现
 @Slf4j
@Component("HUAWEI_OSS")
public class HuaweiFileStrategyImpl extends AbstractFileStrategy {
    private static OkHttpClient httpClient = new OkHttpClient.Builder().followRedirects(false)
            .retryOnConnectionFailure(false).cache(null).build();


    public HuaweiFileStrategyImpl(FileServerProperties fileProperties, FileMapper fileMapper) {
        super(fileProperties, fileMapper);
    }

    private static Request.Builder getBuilder(TemporarySignatureResponse res) {
        Request.Builder builder = new Request.Builder();
        for (Map.Entry<String, String> entry : res.getActualSignedRequestHeaders().entrySet()) {
            builder.header(entry.getKey(), entry.getValue());
        }
        return builder.url(res.getSignedUrl());
    }

    private static String getResponse(Request request) throws IOException {
        Call c = httpClient.newCall(request);
        Response res = c.execute();
        if (res.body() != null) {
            String content = res.body().string();
            return content;
        }
        res.close();
        return StrPool.EMPTY;
    }

    @Override
    protected void uploadFile(File file, MultipartFile multipartFile, String bucket) throws Exception {
        FileServerProperties.Huawei huawei = fileProperties.getHuawei();

        //生成文件名
        String uniqueFileName = getUniqueFileName(file);
        String path = getPath(file.getBizType(), uniqueFileName);
        bucket = StrUtil.isEmpty(bucket) ? huawei.getBucket() : bucket;

        try (ObsClient obsClient = new ObsClient(huawei.getAccessKey(), huawei.getSecretKey(), huawei.getEndpoint())) {
//            createBucket(obsClient, bucket);

            PutObjectRequest request = new PutObjectRequest(bucket, path, multipartFile.getInputStream());
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType(multipartFile.getContentType());
            metadata.setContentDisposition("attachment;fileName=" + URLUtil.encode(file.getOriginalFileName()));
            request.setMetadata(metadata);
            obsClient.putObject(request);

            String url = huawei.getUrlPrefix() + bucket + StrPool.SLASH + path;
            file.setUrl(url);
        }
        file.setBucket(bucket);
        file.setPath(path);
        file.setUniqueFileName(uniqueFileName);
        file.setStorageType(FileStorageType.HUAWEI_OSS);
    }

    private void createBucket(ObsClient obsClient, String bucket) throws ObsException {
        boolean exists = obsClient.headBucket(bucket);
        if (!exists) {
            ObsBucket obsBucket = new ObsBucket();
            obsBucket.setBucketName(bucket);
            obsBucket.setLocation(fileProperties.getHuawei().getLocation());
//        // 设置桶访问权限为公共读,默认是私有读写
//        obsBucket.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ);
            obsClient.createBucket(obsBucket);
        }
    }

    @Override
    @SneakyThrows
    public boolean delete(FileDeleteBO file) {
        FileServerProperties.Huawei huawei = fileProperties.getHuawei();
        try (ObsClient obsClient = new ObsClient(huawei.getAccessKey(), huawei.getSecretKey(),
                huawei.getEndpoint())) {
            obsClient.deleteObject(file.getBucket(), file.getPath());
        }
        return true;
    }

    @Override
    @SneakyThrows
    public Map<String, String> findUrl(List<FileGetUrlBO> fileGets) {
        FileServerProperties.Huawei huawei = fileProperties.getHuawei();
        Set<String> publicBucket = fileProperties.getPublicBucket();

        Map<String, String> map = new LinkedHashMap<>(CollHelper.initialCapacity(fileGets.size()));
        try (ObsClient obsClient = new ObsClient(huawei.getAccessKey(), huawei.getSecretKey(),
                huawei.getEndpoint())) {
            for (FileGetUrlBO fileGet : fileGets) {
                String bucket = StrUtil.isEmpty(fileGet.getBucket()) ? huawei.getBucket() : fileGet.getBucket();
                try {
                    if (CollUtil.isNotEmpty(publicBucket) && publicBucket.contains(bucket)) {
                        StringBuilder url = new StringBuilder(huawei.getUrlPrefix())
                                .append(fileGet.getBucket())
                                .append(StrPool.SLASH)
                                .append(fileGet.getPath());
                        map.put(fileGet.getPath(), url.toString());
                    } else {
                        TemporarySignatureRequest req = new TemporarySignatureRequest(HttpMethodEnum.GET, 300);
                        req.setBucketName(fileGet.getBucket());
                        req.setObjectKey(fileGet.getPath());
                        req.setExpires(huawei.getExpiry());
                        TemporarySignatureResponse res = obsClient.createTemporarySignature(req);
                        map.put(fileGet.getPath(), res.getSignedUrl());
                    }
                } catch (Exception e) {
                    log.warn("加载文件url地址失败,请确保yml中第三方存储参数配置正确. bucket={}, , 文件名={} path={}", bucket, fileGet.getOriginalFileName(), fileGet.getPath(), e);
                    map.put(fileGet.getPath(), StrPool.EMPTY);
                }
            }
        }
        return map;
    }


}
ALI_OSS的文件上传实现
@Slf4j

@Component("ALI_OSS")
public class AliFileStrategyImpl extends AbstractFileStrategy {
    public AliFileStrategyImpl(FileServerProperties fileProperties, FileMapper fileMapper) {
        super(fileProperties, fileMapper);
    }

    @Override
    protected void uploadFile(File file, MultipartFile multipartFile, String bucket) throws Exception {
        FileServerProperties.Ali ali = fileProperties.getAli();
        OSS ossClient = new OSSClientBuilder().build(ali.getEndpoint(), ali.getAccessKeyId(),
                ali.getAccessKeySecret());
        if (StrUtil.isEmpty(bucket)) {
            bucket = ali.getBucket();
        }
        if (!ossClient.doesBucketExist(bucket)) {
            ossClient.createBucket(bucket);
        }

        //生成文件名
        String uniqueFileName = getUniqueFileName(file);

        // 企业id/功能点/年/月/日/file
        String path = getPath(file.getBizType(), uniqueFileName);

        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentDisposition("attachment;fileName=" + file.getOriginalFileName());
        metadata.setContentType(file.getContentType());
        PutObjectRequest request = new PutObjectRequest(bucket, path, multipartFile.getInputStream(), metadata);
        PutObjectResult result = ossClient.putObject(request);

        log.info("result={}", JsonUtil.toJson(result));
        String url = ali.getUrlPrefix() + bucket + StrPool.SLASH + path;
        file.setUrl(url);
        file.setUniqueFileName(uniqueFileName);
        file.setBucket(bucket);
        file.setPath(path);
        file.setStorageType(FileStorageType.ALI_OSS);

        ossClient.shutdown();
    }

    @Override
    public boolean delete(FileDeleteBO file) {
        FileServerProperties.Ali ali = fileProperties.getAli();
        String bucketName = StrUtil.isEmpty(file.getBucket()) ? ali.getBucket() : file.getBucket();
        OSS ossClient = new OSSClientBuilder().build(ali.getEndpoint(), ali.getAccessKeyId(), ali.getAccessKeySecret());
        ossClient.deleteObject(bucketName, file.getPath());
        ossClient.shutdown();
        return true;
    }

    @Override
    public Map<String, String> findUrl(List<FileGetUrlBO> fileGets) {
        OSS ossClient = createOss();
        Set<String> publicBucket = fileProperties.getPublicBucket();
        FileServerProperties.Ali ali = fileProperties.getAli();
        Map<String, String> map = new LinkedHashMap<>(CollHelper.initialCapacity(fileGets.size()));


        for (FileGetUrlBO fileGet : fileGets) {
            String bucket = StrUtil.isEmpty(fileGet.getBucket()) ? ali.getBucket() : fileGet.getBucket();
            try {
                if (CollUtil.isNotEmpty(publicBucket) && publicBucket.contains(bucket)) {
                    StringBuilder url = new StringBuilder(ali.getUrlPrefix())
                            .append(fileGet.getBucket())
                            .append(StrPool.SLASH)
                            .append(fileGet.getPath());
                    map.put(fileGet.getPath(), url.toString());
                } else {
                    map.put(fileGet.getPath(), generatePresignedUrl(bucket, fileGet.getPath()));
                }
            } catch (Exception e) {
                log.warn("加载文件url地址失败,请确保yml中第三方存储参数配置正确. bucket={}, , 文件名={} path={}", bucket, fileGet.getOriginalFileName(), fileGet.getPath(), e);
                map.put(fileGet.getPath(), StrPool.EMPTY);
            }
        }
        ossClient.shutdown();
        return map;
    }

    /**
     * 获取一个ossclient
     *
     * @return
     */
    public OSS createOss() {
        FileServerProperties.Ali ali = fileProperties.getAli();
        String accessKeyId = ali.getAccessKeyId();
        String accessKeySecret = ali.getAccessKeySecret();
        String endPoint = ali.getEndpoint();
        return new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
    }

    /**
     * 获取有访问权限的路径地址
     *
     * @param bucketName
     * @param key
     * @return
     */
    private String generatePresignedUrl(String bucketName, String key) {
        FileServerProperties.Ali ali = fileProperties.getAli();
        OSS oss = createOss();
        Date date = new Date(System.currentTimeMillis() + ali.getExpiry());
        URL url = oss.generatePresignedUrl(bucketName, key, date);
        return url.toString();
    }
}
CLOUD_FLARE实现文件上传
@Slf4j
@Component("CLOUD_FLARE")
public class CloudFlareStrategyImpl extends AbstractFileStrategy {


    @Value("${cf.account.id}")
    String CF_ACCOUNT_ID ;
    @Value("${cf.account.token}")
    String token ;

    @Resource
    private CloudFlareApi cloudFlareApi;

    public CloudFlareStrategyImpl(FileServerProperties fileProperties, FileMapper fileMapper) {
        super(fileProperties, fileMapper);
    }

    @Override
    public boolean delete(FileDeleteBO fileDeleteBO) {
        return false;
    }

    @Override
    public Map<String, String> findUrl(List<FileGetUrlBO> fileGets) {
        return null;
    }

    @Override
    protected void uploadFile(File file, MultipartFile multipartFile, String bucket) throws Exception {
        String contentType = file.getContentType();
        if (contentType.startsWith("video")) {
            uploadVideo(file, multipartFile);
        } else {
            String url = CF_BASE_URL + CF_ACCOUNT_ID + "/images/v1";
            OkHttpClient client = new OkHttpClient();
            RequestBody fileBody = RequestBody.create(MediaType.parse(contentType), multipartFile.getBytes());
            RequestBody requestBody = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM)
                    .addFormDataPart("file", multipartFile.getName(), fileBody)
                    .build();
            Request request = new Request.Builder().url(url).addHeader("Authorization", token).post(requestBody).build();
            //请求超时时间5s
            client.newBuilder().readTimeout(500, TimeUnit.SECONDS).build().newCall(request);
            final Call call = client.newCall(request);
            try (Response response = call.execute();) {
                assert response.body() != null;
                String string = response.body().string();
                CloudFlareResult<CloudFlareImagesResult> cloudFlareResult = JSONObject.parseObject(string, new TypeReference<CloudFlareResult<CloudFlareImagesResult>>() {
                });
                CloudFlareImagesResult result = cloudFlareResult.getResult();
                file.setUrl(result.getVariants().get(0)).setUniqueFileName(result.getId());
            } catch (Exception e) {
                log.error("uploadFile fail:{}", e.getMessage(), e);
                throw new BizException("uploadFile fail");
            }
        }

    }

    private void uploadVideo(File file, MultipartFile multipartFile) throws Exception {
        String contentType = file.getContentType();
        String url = CF_BASE_URL + CF_ACCOUNT_ID + "/stream";

        OkHttpClient client = new OkHttpClient();
        RequestBody fileBody = RequestBody.create(MediaType.parse(contentType), multipartFile.getBytes());
        RequestBody requestBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("file", multipartFile.getName(), fileBody)
                .build();
        Request request = new Request.Builder().url(url).addHeader("Authorization", token).post(requestBody).build();
        //请求超时时间5s
        client.newBuilder()
                .connectTimeout(500, TimeUnit.SECONDS)
                .readTimeout(500, TimeUnit.SECONDS)
                .callTimeout(500, TimeUnit.SECONDS)
                .writeTimeout(500, TimeUnit.SECONDS)
                .build()
                .newCall(request);
        final Call call = client.newCall(request);
        try (Response response = call.execute();) {
            assert response.body() != null;
            String string = response.body().string();
            CloudFlareResult<CloudFlareVideoResult> cloudFlareResult = JSONObject.parseObject(string, new TypeReference<CloudFlareResult<CloudFlareVideoResult>>() {
            });
            CloudFlareVideoResult result = cloudFlareResult.getResult();
            file.setUrl(result.getPlayback().getOrDefault("hls", "")).setFileMd5(result.getUid()).setUniqueFileName(result.getThumbnail());
        } catch (Exception e) {
            log.error("uploadFile fail:{}", e.getMessage(), e);
            throw new BizException("uploadFile fail");
        }
    }


}
QINIU_OSS的文件上传
@Component("QINIU_OSS")
public class QiNiuFileStrategyImpl extends AbstractFileStrategy {
    private static StringMap PUT_POLICY = new StringMap();

    static {
        PUT_POLICY.put("returnBody", "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"width\":$(imageInfo.width), \"height\":${imageInfo.height}}");
    }

    private final UploadManager uploadManager;
    private final BucketManager bucketManager;
    private final Auth auth;

    public QiNiuFileStrategyImpl(FileServerProperties fileProperties, FileMapper fileMapper,
                                 UploadManager uploadManager, BucketManager bucketManager, Auth auth) {
        super(fileProperties, fileMapper);
        this.uploadManager = uploadManager;
        this.bucketManager = bucketManager;
        this.auth = auth;
    }

    /**
     * 获取上传凭证
     *
     * @return
     */
    private String getUploadToken(String bucket) {
        FileServerProperties.QiNiu qiNiu = fileProperties.getQiNiu();
        String token = this.auth.uploadToken(bucket, null, qiNiu.getExpiry(), PUT_POLICY);
        log.info("token={}", token);
        return token;
    }

    @Override
    protected void uploadFile(File file, MultipartFile multipartFile, String bucket) throws Exception {
        FileServerProperties.QiNiu qiNiu = fileProperties.getQiNiu();
        if (StrUtil.isEmpty(bucket)) {
            bucket = qiNiu.getBucket();
        }

        //生成文件名
        String uniqueFileName = getUniqueFileName(file);

        // 企业id/功能点/年/月/日/file
        String path = getPath(file.getBizType(), uniqueFileName);

        StringMap params = new StringMap();
        params.put("x-qn-meta-contentDisposition", "attachment;fileName=" + file.getOriginalFileName());
        Response response = this.uploadManager.put(multipartFile.getInputStream(), path, getUploadToken(bucket),
                params, file.getContentType());

        log.info("response={}", JsonUtil.toJson(response));

        if (response.statusCode == 200) {
            DefaultPutRet defaultPutRet = JsonUtil.parse(response.bodyString(), DefaultPutRet.class);
            log.info("defaultPutRet={}", JsonUtil.toJson(defaultPutRet));

            file.setUniqueFileName(uniqueFileName);
            file.setBucket(bucket);
            file.setPath(path);
        }
        file.setUrl(qiNiu.getUrlPrefix() + bucket + StrPool.SLASH + path);
        file.setStorageType(FileStorageType.QINIU_OSS);
    }

    @SneakyThrows
    @Override
    public boolean delete(FileDeleteBO file) {
        FileServerProperties.QiNiu qiNiu = fileProperties.getQiNiu();
        String bucket = StrUtil.isEmpty(file.getBucket()) ? qiNiu.getBucket() : file.getBucket();
        Response response = bucketManager.delete(bucket, file.getPath());
        log.info("response={}", JsonUtil.toJson(response));
        return true;
    }


    @SneakyThrows
    @Override
    public Map<String, String> findUrl(List<FileGetUrlBO> fileGets) {
        Map<String, String> map = new LinkedHashMap<>(CollHelper.initialCapacity(fileGets.size()));

        FileServerProperties.QiNiu qiNiu = fileProperties.getQiNiu();
        Set<String> publicBucket = fileProperties.getPublicBucket();

        for (FileGetUrlBO fileGet : fileGets) {
            String bucket = StrUtil.isEmpty(fileGet.getBucket()) ? qiNiu.getBucket() : fileGet.getBucket();
            try {
                if (CollUtil.isNotEmpty(publicBucket) && publicBucket.contains(bucket)) {
                    StringBuilder url = new StringBuilder(qiNiu.getUrlPrefix())
                            .append(fileGet.getBucket())
                            .append(StrPool.SLASH)
                            .append(fileGet.getPath());
                    map.put(fileGet.getPath(), url.toString());
                } else {
                    DownloadUrl url = new DownloadUrl(qiNiu.getDomain(), false, fileGet.getPath());
                    url.setAttname(fileGet.getOriginalFileName());
                    long deadline = System.currentTimeMillis() / 1000 + qiNiu.getExpiry();
                    String urlString = url.buildURL(auth, deadline);
                    map.put(fileGet.getPath(), urlString);
                }
            } catch (Exception e) {
                log.warn("加载文件url地址失败,请确保yml中第三方存储参数配置正确. bucket={}, , 文件名={} path={}", bucket, fileGet.getOriginalFileName(), fileGet.getPath(), e);
                map.put(fileGet.getPath(), StrPool.EMPTY);
            }
        }
        return map;
    }


}

LOCAL文件上传
@Slf4j

@Component("LOCAL")
public class LocalFileStrategyImpl extends AbstractFileStrategy {
    public LocalFileStrategyImpl(FileServerProperties fileProperties, FileMapper fileMapper) {
        super(fileProperties, fileMapper);
    }

    @Override
    protected void uploadFile(File file, MultipartFile multipartFile, String bucket) throws Exception {
        FileServerProperties.Local local = fileProperties.getLocal();
        bucket = StrUtil.isEmpty(bucket) ? local.getBucket() : bucket;

        //生成文件名
        String uniqueFileName = getUniqueFileName(file);
        // 相对路径
        String path = getPath(file.getBizType(), uniqueFileName);
        // web服务器存放的绝对路径
        String absolutePath = Paths.get(local.getStoragePath(), bucket, path).toString();

        // 存储文件
        java.io.File outFile = new java.io.File(absolutePath);
        FileUtils.writeByteArrayToFile(outFile, multipartFile.getBytes());

        // 返回数据
        String url = local.getUrlPrefix() + bucket + StrPool.SLASH + path;
        file.setUrl(url);
        file.setUniqueFileName(uniqueFileName);
        file.setPath(path);
        file.setBucket(bucket);
        file.setStorageType(FileStorageType.LOCAL);
    }

    @Override
    public boolean delete(FileDeleteBO file) {
        FileServerProperties.Local local = fileProperties.getLocal();
        java.io.File ioFile = new java.io.File(Paths.get(local.getStoragePath(), file.getBucket(), file.getPath()).toString());
        FileUtils.deleteQuietly(ioFile);
        return true;
    }

    @Override
    public Map<String, String> findUrl(List<FileGetUrlBO> fileGets) {
        Map<String, String> map = new LinkedHashMap<>(CollHelper.initialCapacity(fileGets.size()));
        // 方式1 取上传时存的url (多查询一次数据库)
//        List<String> paths = fileGets.stream().map(FileGetUrlBO::getPath).collect(Collectors.toList());
//        List<File> list = fileMapper.selectList(Wraps.<File>lbQ().eq(File::getPath, paths));
//        list.forEach(item -> map.put(item.getPath(), item.getUrl()));

        // 方式2 重新拼接 (urlPrefix 可能跟上传时不一样)
        FileServerProperties.Local local = fileProperties.getLocal();
        fileGets.forEach(item -> {
            StringBuilder url = new StringBuilder(local.getUrlPrefix())
                    .append(item.getBucket())
                    .append(StrPool.SLASH)
                    .append(item.getPath());
            map.put(item.getPath(), url.toString());
        });
        return map;
    }
}

具体使用

controller
  /**
     * 上传文件
     */
    @ApiOperation(value = "附件上传", notes = "附件上传")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "附件", dataType = DATA_TYPE_MULTIPART_FILE, allowMultiple = true, required = true),
    })
    @PostMapping(value = "/anyone/upload")
    @SysLog("上传附件")
    public R<FileResultVO> upload(@RequestParam(value = "file") MultipartFile file,
                                  @Validated FileUploadVO attachmentVO) {
        // 忽略路径字段,只处理文件类型
        if (file.isEmpty()) {
                return R.validFail(BASE_VALID_PARAM.build("请上传有效文件"));
        }
        return R.success(baseService.upload(file, attachmentVO));
    }
判断具体使用哪个上传
 /**
     * 文件上传
     *
     * @param file         文件
     * @param fileUploadVO 文件上传参数
     * @return 文件对象
     */
    public File upload(MultipartFile file, FileUploadVO fileUploadVO) {
        FileStrategy fileStrategy = getFileStrategy(FileStorageType.CLOUD_FLARE);
        return fileStrategy.upload(file, fileUploadVO.getBucket(), fileUploadVO.getBizType());
    }

    private FileStrategy getFileStrategy(FileStorageType storageType) {
        storageType = storageType == null ? fileServerProperties.getStorageType() : storageType;
        FileStrategy fileStrategy = contextStrategyMap.get(storageType.name());
        ArgumentAssert.notNull(fileStrategy, "请配置正确的文件存储类型");
        return fileStrategy;
    }

getFileStrategy方法会确定最终使用哪个策略

end!!!

【SpringBoot + Vue2】策略模式之 实现多种方式的文件上传 策略设计模式是一种行为设计模式。当在处理一个业务时,有多种处理方式,并且需要再运行时决定使哪一种具体实现时,就会使用策略模式。我们定义一个接口(就比如接下来要实现的文件上传接口)我们定义所需要实现的策略实现类 A、B、C、D(也就是项目中所使用的四种策略阿里云Oss上传、腾讯云Cos上传、七牛云Kodo上传、本地上传)我们通过策略上下文来调用策略接口,并选择所需要使用的策略上面就是策略模式的简单概述,那么我们接下来就新建一个项目来实际演练一下。 阅读详情

相关推荐

@RequiredArgsConstructor注解

小编最近在项目里看到有的同事用到了Lombok中的一个@RequiredArgsConstructor,带着好奇发现这个东西就是简化了一些@Autowired注解,想想如果一个Service还有几十个注入,这样就要写上几十个@Autowired,这样代码显示很臃肿哈。有了@RequiredArgsConstructor注解,我们就可以减少@Autowired的书写。用过的人都说好哈,下面带大家一起使用一下!

Rsun2018的博客 4238

基于mybatis plus实现数据源动态添加、删除、切换,自定义数据源

简介 基于springboot,mybatis plus集成了一套多数据源的解决方案,在使用时引入相应的插件dynamic-datasource-spring-boot-starter,可以实现数据源的动态添加、删除等功能,对于多租户或者分库等操作可以根据AOP切面代理到不同的数据源、实现单一系统数据隔离的目的。 代码示例 mavne依赖 <!--mybatis-plus--> &l...

starsray的博客 8272

致远OA系统表单相关操作记录(一)

致远OA系统表单相关操作

weixin_59666050的博客 6102

@NoArgsConstructor、@AllArgsConstructor、@RequiredArgsConstructor的区别以及在springboot常用地方

文章目录1. 先说结论2. 代码解析区别1. @AllArgsConstructor2. @RequiredArgsConstructor3. 场景使用---代替@Autowired注入bean对象1. @AllArgsConstructor2. @RequiredArgsConstructor3. @RequiredArgsConstructor 与 @AllArgsConstructor 在注入bean上的区别4. 总结 1. 先说结论 区别: @NoArgsConstructor:生成无参的构造方法

搏·梦的博客 2万+

PADS导出PCB正反面丝印为CAD文件的方法

本文介绍如何将PADS绘制的pcb格式的PCB文件顶底层丝印及板框导出为CAD的dxf文件格式,并且将底层丝印进行镜像为正常视角

luguodeyo的博客 3294

HCIA重点知识

华为认证ICT工程师,是华为认证体系中用于标识个人能力在某一技术领域达到工程师级别的证明,表示通过认证的人员具备安装、配置、运行 ICT 设备,并进行基础故障排除的能力。抽象语言 -----> 编码 -----> 二进制 -----> 电信号 -----> 处理电信号信号的转换标准:协议,是一种允许电子设备相互交流的一系列标准的规则。即开放系统参考模型OSI/RM,简称“OSI”。OSI参考模型将计算机网络分为七个层次,自上而下依次为:应用层,表示层,会话层,传输层,网络层,数据链路层,物理层。1、应用层:

Awen0201的博客 2542

@RequiredArgsConstructor的作用

减少代码臃肿,不用重复使用autowired当使用@autowired注入的时候,有时候会发生警告(我之前的采取方法无非就是替换成resource注解)或者采用构造器的方法进行注入但是今天了解到了@RequiredArgsConstructor。

m0_56957320的博客 2066

【干货攻略】Oracle报错篇 ORA-01378 磁盘扇区大小不兼容问题

本期将为大家分享“ORA-01378 磁盘扇区大小不兼容”报错的问题解决方案。

PWY13148的专栏 1437

【SpringBoot 】策略模式 之 一键切换文件上传方式

策略模式是指有一定行动内容的相对稳定的策略名称。策略模式在古代中又称“计策”,简称“计”,如《汉书·高帝纪上》:“汉王从其计”。这里的“计”指的就是计谋、策略。策略模式具有相对稳定的形式,如“避实就虚”、“出奇制胜”等。一定的策略模式,既可应用于战略决策,也可应用于战术决策;既可实施于大系统的全局性行动,也可实施于大系统的局部性行动。我们定义一个接口(就比如接下来要实现的文件上传接口)

木字楠的博客 1581

JHU ICBM DTI Atlas纤维束模板介绍

JHU ICBM DTI atlas 纤维束的定位与功能介绍

machinelearning_er的博客 6424

手机直连低轨卫星通信:架构、关键技术和未来展望

【摘 要】借助低轨卫星星座全时全域覆盖优势,手机直连卫星通信预期成为6G重要特征之一。首先介绍了手机直连卫星的测试验证、标准化与商业项目发展现状。其次,介绍了基于透明转发、部分可再生处理、完全可再生处理、集成接入和回传的四种手机直连低轨卫星网络架构及组网方式。通过分析手机直连低轨卫星网络场景下高移动性与大传输时延等带来的接入与传输问题,提出对地面移动通信体制进行适应性改进的关键技术方案。最后,探讨了未来手机直连低轨卫星发展发向和潜在思路。通过上述阐述与分析,提供未来发展手机直连低轨卫星通信的可行路径。【关

fzq0625的博客 1707

SpringBoot一键切换文件上传方式(巧用策略模式)

策略模式是指有一定行动内容的相对稳定的策略名称。策略模式在古代中又称“计策”,简称“计”,如《汉书·高帝纪上》:“汉王从其计”。这里的“计”指的就是计谋、策略。策略模式具有相对稳定的形式,如“避实就虚”、“出奇制胜”等。一定的策略模式,既可应用于战略决策,也可应用于战术决策;既可实施于大系统的全局性行动,也可实施于大系统的局部性行动。上面的概述可能大家会看的摸不着头脑,简单来说就是:我们定义一个接口(就比如接下来要实现的文件上传接口)

程序员高级码农的博客 1038

配置 SAP Fiori 服务的 ICF 节点:从 SICF 激活到访问链路打通的完整实践

在SAP Fiori项目实施中,ICF节点配置是关键前置条件却常被忽视。ICF(Internet Communication Framework)作为HTTP请求入口,需要通过SICF事务码激活相关服务节点,否则即使应用开发完善,用户仍可能遇到页面无法访问等问题。典型问题表现为:磁贴可点击但页面空白、资源加载失败等。激活路径主要涉及三组节点:bsp分支下的管理入口、ui5_ui5分支下的应用资源,以及public/bc下的公共资源。项目实施中需特别注意同名服务在不同分支下的差异化作用,确保完整链路通畅。IC

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 264

策略模式实现文件上传

策略模式上传文件(超详细)

qq_68512683的博客 577

uniapp微信小程序开发:解决Video播放m3u8视频流非卡顿问题,使用video视频标签播放M3U8视频流或直播流总是加载一卡一卡的体验非常差的情况【多种优化方案提升流畅度和缓冲方案示例源码】

uniapp微信小程序video播放m3u8视频流卡,uniapp video在微信小程序播放m3u8格式视频总是加载频繁卡顿,Uniapp微信小程序苹果ios真机播放m3u8很卡加载不流畅怎么办,uni-App如何解决小程序端video播放视频流M3U8格式出现卡顿情况,uniapp播放m3u8直播流卡顿如何优化?uniapp m3u8格式视频加载,.m3u8监控视频,uniapp微信小程序使用video组件播放M3U8视频卡顿,uniapp微信小程序视频播放卡顿如何解决,uniapp 打包微信小程序播放

✅ 精选推荐文章 2987

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

SpringBoot:策略模式实现文件上传方式的灵活切换

策略模式是指有一定行动内容的相对稳定的策略名称,简单来说就是:我们定义一个接口(就比如接下来要实现的文件上传接口)我们定义所需要实现的策略实现类 A、B、C、D(也就是项目中所使用的四种策略阿里云Oss上传、腾讯云Cos上传、七牛云Kodo上传、本地上传)我们通过策略上下文来调用策略接口,并选择所需要使用的策略上面就是策略模式的简单概述,更详细请查看:《状态模式、策略模式、责任链模式(详解)那么我们接下来就新建一个项目来实际演练一下。上述只是对于策略模式的简单实践。

竹林幽深 310

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

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

代码实战,基于策略模式实现文件上传到本地和腾讯云COS。

l481282474的博客 325

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

利用策略模式与Spring Boot实现灵活的文件上传功能:多策略选择与动态实现

*@Service@Override// 实现本地文件上传逻辑@Service@Override// 实现云端文件上传逻辑以上示例展示了如何结合策略模式和Spring Boot来实现动态文件上传功能。通过定义不同的上传策略类,您可以根据需要选择特定的上传方式,并且这些策略类可以轻松地替换、扩展或新增,使得系统更加灵活和可维护。

weixin_43709538的博客 1447

用@Resource做策略模式,不用if了

背景:领导要我把三种上传文件的方法合并起来,不要用if,用策略模式,之前没写过,找了一会资料,写了个简单的 首先创建一个公共接口 public interface UploadService { //共同方法行为 R<UploadResp> toUploadBase(UploadBaseReq uploadStrategy); } 实体类参数包括上传类型 @Data @ApiModel @JsonIgnoreProperties(ignoreUnknown = true) pu

weixin_38505164的博客 941

【SpringBoot 】策略模式 :一键切换文件上传方式

【SpringBoot 】策略模式 :一键切换文件上传方式

m0_57046985的博客 586

springboot 文件上传 各种姿势 解锁,策略模式简单运用

总结:从文件上传谈 策略模式运用 ,虚拟路径配置,纸上得来终觉浅,绝知此事要躬行。 单文件,多文件,base64 几种上传方式 。具体细节参考我的代码库https://gitee.com/www.lyc.com/lyc-demo.git     /** * tip 小知识这里其实有多套(本地 阿里 七牛,又拍,腾讯) 实现 * 可以根据 传参不同 从容器 取对于的实现...

weixin_34235371的博客 512

【前后端分离博客】学习笔记04 --- 文件上传-策略模式

上述只是对于策略模式的简单实践。我们可以通过网站全局配制结合前端界面来完成选择使用哪个平台来进行文件的上传。当我们选中哪种上传模式,那么后台则会执行该上传方式。

乌云的博客 933

SpringBoot+Vue实现简单的文件上传(策略模式)

前两篇文章,我们上传了txt、Excel文件,其实文件类型有很多种,如果我们的upload组件没有上传文件类型的限制,那么同一个接口会上传多种文件,而类型不一样,其处理的方式也不一样。一种方式是写if判断,我们判断其类型,然后做特定的处理,那样代码会有大量if判断;另外一个可以使用策略模式来处理,简单来说就是定义一个接口,多个实现类,不同的文件类型使用不同的实现类。

weixin_45732391的博客 458

Springboot策略模式实现文件上传功能(Windows/Linux本地,oss,cos)

2:application.yml: 2.1:腾讯云信息查看:secretId+secretKey在访问密钥里面查看 (4):文件上传策略: (5):本地路径上传策略方法实现层:WindowsUploadStrategyImpl: (6):controller层:更新用户头像为例: (7):userInfoService.updateUserAvatar层及其实现: (8):uploadStrategyContext.executeUploadStrategy: (9):抽象上传模板

justleavel的博客 1907
上一篇: 整合stripe线上支付收款
下一篇: 使用equals遇到的bug
pywanggui
博客等级 码龄12年 6粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pywanggui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值