DEMO流程
- 传入一个需要下载并上传的url地址
- 下载文件
- 上传文件并返回OSS的url地址
springboot pom文件依赖
<?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 文件配置
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 工具类
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
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
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
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
public interface FileService {
String uploadJavaVideo(String url) throws Exception;
}
FileServiceImpl
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 类
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 请求