springboot 通过url下载文件并上传到OSS

DEMO流程

  • 传入一个需要下载并上传的url地址
  • 下载文件
  • 上传文件并返回OSS的url地址

springboot pom文件依赖

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.15</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springboot-rocketmq</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-demo</name>
    <description>springboot-demo</description>
    <properties>
        <java.version>11</java.version>
        <rocketmq-client-java-version>5.1.3</rocketmq-client-java-version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.13</version>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.22</version>
        </dependency>

        <!-- 阿里云oss -->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.13.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

application.yml 文件配置

yaml 复制代码
ali:
  oss:
    #oss end-point
    end-point: 
    #oss access-key-id
    access-key-id: 
    #oss access-key-secret
    access-key-secret: 
    #oss bucket-name
    bucket-name: 
    ali-url: https://${ali.oss.bucket-name}.${ali.oss.end-point}/

FileUtil 工具类

java 复制代码
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.IdUtil;

import java.io.File;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class FileUtil {

    private static final String projectUrl = System.getProperty("user.dir").replaceAll("\\\\", "/");

    public static void deleteFiles(String path) {
        File file = new File(path);
        if (file.exists()) {
            if (file.isDirectory()) {
                File[] temp = file.listFiles(); //获取该文件夹下的所有文件
                for (File value : temp) {
                    deleteFile(value.getAbsolutePath());
                }
            } else {
                file.delete(); //删除子文件
            }
            file.delete(); //删除文件夹
        }
    }

    public static void deleteFile(String path){
        File dest = new File(path);
        if (dest.isFile() && dest.exists()) {
            dest.delete();
        }
    }

    public static String getNewFileRootPath(){
        return projectUrl+File.separator+ IdUtil.simpleUUID();
    }

    public static String getFileNameFromUrl(String url) {
        Pattern pattern = Pattern.compile("[^/]*$");
        Matcher matcher = pattern.matcher(url);
        if (matcher.find()) {
            return matcher.group();
        }
        return "";
    }

    /**
     * 获取扩展名
     * @param urlPath
     * @return {@link String}
     */
    public static String getExtName(String urlPath) {
        String fileName = getFileNameFromUrl(urlPath);
        return FileNameUtil.extName(fileName);
    }
}

请求配置 RestTemplateConfig

java 复制代码
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory requestFactory) {
        return new RestTemplate(requestFactory);
    }

    @Bean
    public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setReadTimeout(10000);
        factory.setConnectTimeout(10000);
        factory.setHttpClient(httpClient());
        return factory;
    }

    /**
     * @return
     */
    @Bean
    public HttpClient httpClient() {
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();

        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);

        //设置整个连接池最大连接数
        connectionManager.setMaxTotal(500);

        //MaxPerRoute路由是对maxTotal的细分,每个主机的并发,这里route指的是域名
        connectionManager.setDefaultMaxPerRoute(200);
        RequestConfig requestConfig = RequestConfig.custom()
                //返回数据的超时时间
                .setSocketTimeout(20000)
                //连接上服务器的超时时间
                .setConnectTimeout(10000)
                //从连接池中获取连接的超时时间
                .setConnectionRequestTimeout(1000)
                .build();

        return HttpClientBuilder.create()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager)
                .build();
    }
}

阿里组件配置

读取配置类 AliOssProperties

java 复制代码
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "ali.oss")
@Data
public class AliOssProperties {
    /**
     * OSS配置信息
     */
    private String endpoint;

    private String accessKeyId;

    private String accessKeySecret;

    private String bucketName;

    private String aliUrl;
}

OSS组件类 OssComponent

java 复制代码
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;

@Component
@Slf4j
@Getter
public class OssComponent {

    @Resource
    private AliOssProperties aliOssProperties;

    /* -----------------对外功能---------------- */

    /**
     * 单个文件上传(指定文件名(带后缀))
     *
     * @param inputStream 文件
     * @param fileName    文件名(带后缀)
     * @return 返回完整URL地址
     */
    public String uploadFile(String fileDir, InputStream inputStream, String fileName) {
        try {
            this.uploadFile2Oss(fileDir, inputStream, fileName);
            String url = getFileUrl(fileDir, fileName);
            if (url != null && url.length() > 0) {
                return url;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("获取路径失败");
        }
        return "";
    }

    /**
     * 通过文件名获取文完整件路径
     *
     * @param fileUrl 文件名
     * @return 完整URL路径
     */
    public String getFileUrl(String fileDir, String fileUrl) {
        if (fileUrl != null && fileUrl.length() > 0) {
            String[] split = fileUrl.replaceAll("\\\\","/").split("/");
            String url = aliOssProperties.getAliUrl() + fileDir + split[split.length - 1];
            return Objects.requireNonNull(url);
        }
        return null;
    }


    public boolean deleteFile(String fileDir, String fileName) {
        OSS ossClient = new OSSClientBuilder().build(aliOssProperties.getEndpoint(), aliOssProperties.getAccessKeyId(), aliOssProperties.getAccessKeySecret());
        // 删除文件
        ossClient.deleteObject(aliOssProperties.getBucketName(), fileDir + fileName);
        // 判断文件是否存在
        boolean found = ossClient.doesObjectExist(aliOssProperties.getBucketName(), fileDir + fileName);
        // 如果文件存在则删除失败

        return !found;
    }





    /* -----------内部辅助功能------------------------ */

    /**
     * 获取去掉参数的完整路径
     *
     * @param url URL
     * @return 去掉参数的URL
     */
    private String getShortUrl(String url) {
        String[] imgUrls = url.split("\\?");
        return imgUrls[0].trim();
    }


    /**
     * 上传文件(指定文件名)
     *
     * @param inputStream 输入流
     * @param fileName    文件名
     */
    private void uploadFile2Oss(String fileDir, InputStream inputStream, String fileName) {
        OSS ossClient = new OSSClientBuilder().build(aliOssProperties.getEndpoint(), aliOssProperties.getAccessKeyId(), aliOssProperties.getAccessKeySecret());
        String ret;
        try {
            //创建上传Object的Metadata
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(inputStream.available());
            objectMetadata.setCacheControl("no-cache");
            objectMetadata.setHeader("Pragma", "no-cache");
            String contentType = getContentType(fileName.substring(fileName.lastIndexOf(".")));
            if(StrUtil.isNotEmpty(contentType)){
                objectMetadata.setContentType(contentType);
            }
            objectMetadata.setContentDisposition("inline;filename=" + fileName);
            //上传文件
            PutObjectResult putResult = ossClient.putObject(aliOssProperties.getBucketName(), fileDir + fileName, inputStream, objectMetadata);
            ret = putResult.getETag();
            if (StrUtil.isEmpty(ret)) {
                log.error("上传失败,文件ETag为空");
            }
            ossClient.shutdown();
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 请求类型
     *
     * @param filenameExtension :
     * @return :
     */
    private static String getContentType(String filenameExtension) {
        if (FileNameSuffixEnum.BMP.getSuffix().equalsIgnoreCase(filenameExtension)) {
            return "image/bmp";
        }
        if (FileNameSuffixEnum.GIF.getSuffix().equalsIgnoreCase(filenameExtension)) {
            return "image/gif";
        }
        if (FileNameSuffixEnum.JPEG.getSuffix().equalsIgnoreCase(filenameExtension) ||
                FileNameSuffixEnum.JPG.getSuffix().equalsIgnoreCase(filenameExtension) ||
                FileNameSuffixEnum.PNG.getSuffix().equalsIgnoreCase(filenameExtension)) {
            return "image/jpeg";
        }
        if (FileNameSuffixEnum.HTML.getSuffix().equalsIgnoreCase(filenameExtension)) {
            return "text/html";
        }
        if (FileNameSuffixEnum.TXT.getSuffix().equalsIgnoreCase(filenameExtension)) {
            return "text/plain";
        }
        if (FileNameSuffixEnum.VSD.getSuffix().equalsIgnoreCase(filenameExtension)) {
            return "application/vnd.visio";
        }
        if (FileNameSuffixEnum.PPTX.getSuffix().equalsIgnoreCase(filenameExtension) ||
                FileNameSuffixEnum.PPT.getSuffix().equalsIgnoreCase(filenameExtension)) {
            return "application/vnd.ms-powerpoint";
        }
        if (FileNameSuffixEnum.DOCX.getSuffix().equalsIgnoreCase(filenameExtension) ||
                FileNameSuffixEnum.DOC.getSuffix().equalsIgnoreCase(filenameExtension)) {
            return "application/msword";
        }
        if (FileNameSuffixEnum.XML.getSuffix().equalsIgnoreCase(filenameExtension)) {
            return "text/xml";
        }
        if (FileNameSuffixEnum.PDF.getSuffix().equalsIgnoreCase(filenameExtension)) {
            return "application/pdf";
        }
        return "";
    }


}

@Getter
enum FileNameSuffixEnum {

    /**
     * 文件后缀名
     */
    BMP(".bmp", "bmp文件"),
    GIF(".gif", "gif文件"),
    JPEG(".jpeg", "jpeg文件"),
    JPG(".jpg", "jpg文件"),
    PNG(".png", "png文件"),
    HTML(".html", "HTML文件"),
    TXT(".txt", "txt文件"),
    VSD(".vsd", "vsd文件"),
    PPTX(".pptx", "PPTX文件"),
    DOCX(".docx", "DOCX文件"),
    PPT(".ppt", "PPT文件"),
    DOC(".doc", "DOC文件"),
    XML(".xml", "XML文件"),
    PDF(".pdf", "PDF文件");

    /**
     * 后缀名
     */
    private final String suffix;

    /**
     * 描述
     */
    private final String description;

    FileNameSuffixEnum(String suffix, String description) {
        this.suffix = suffix;
        this.description = description;
    }
}

文件服务

FileService
java 复制代码
public interface FileService {
    String uploadJavaVideo(String url) throws Exception;
}
FileServiceImpl
java 复制代码
import cn.hutool.core.util.IdUtil;
import com.example.springbootrocketmq.config.OssComponent;
import com.example.springbootrocketmq.service.FileService;
import com.example.springbootrocketmq.utils.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.io.FileInputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;

@Slf4j
@Service
public class FileServiceImpl implements FileService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private OssComponent ossComponent;

    @Override
    public String uploadJavaVideo(String url) throws Exception {
        String extName = FileUtil.getExtName(url);//获取扩展名称
        String fileName = IdUtil.simpleUUID()+"."+extName;
        log.info("fileName:{}",fileName);
        String newFileRootPath = FileUtil.getNewFileRootPath();
        File rootFile = new File(newFileRootPath);
        if(!rootFile.exists()){
            rootFile.mkdirs();
        }
        String toPath = newFileRootPath+ File.separator + fileName;
        try {
            log.info("toPath:{}",toPath);
            uploadBigFile(url,toPath);
            return ossComponent.uploadFile("demo/",new FileInputStream(toPath),fileName);
        } finally {
            FileUtil.deleteFiles(newFileRootPath);
        }
    }

    /**
     * 下载文件
     * @param url
     * @param toPath
     * @throws Exception
     */
    public void uploadBigFile(String url, String toPath) throws Exception {
        //定义请求头的接收类型
        RequestCallback requestCallback = request -> request.getHeaders()
                .setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));
        //对响应进行流式处理而不是将其全部加载到内存中
        restTemplate.execute(url, HttpMethod.GET, requestCallback, clientHttpResponse -> {
            Files.copy(clientHttpResponse.getBody(), Paths.get(toPath));
            return null;
        });
    }
}

测试 TestController 类

java 复制代码
import com.example.springbootrocketmq.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping("/")
public class TestController {

    @Autowired
    private FileService fileService;

    @GetMapping("/uploadFileToOss")
    public Object uploadJavaVideo(String url) {
        try {
            return fileService.uploadJavaVideo(url);
        }catch (Exception e){
            log.error("上传转码异常,异常原因e:{}",e);
        }
        return null;
    }
}

启动服务 用 postman 请求

相关推荐
XiaoLeisj2 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck2 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei2 小时前
java的类加载机制的学习
java·学习
码农小旋风3 小时前
详解K8S--声明式API
后端
Peter_chq3 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
Yaml44 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~4 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616884 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
aloha_7894 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
记录成长java5 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet