解决文件上传问题

This commit is contained in:
easonzhu 2025-02-04 16:43:04 +08:00
parent 494970db37
commit 54cafd2aba
5 changed files with 86 additions and 37 deletions

View File

@ -91,9 +91,9 @@
<version>4.2.1</version>
</dependency>
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.27.2</version>
<groupId>org.csource</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.31-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.github.whvcse</groupId>

View File

@ -1,15 +1,57 @@
package com.upchina.common.config;
import com.github.tobato.fastdfs.FdfsClientConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.context.annotation.Import;
import org.springframework.jmx.support.RegistrationPolicy;
import java.io.IOException;
import java.util.Arrays;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
@Configuration
@Import(FdfsClientConfig.class)
// 解决jmx重复注册bean的问题
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import org.csource.common.MyException;
import org.csource.fastdfs.*;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.stereotype.Component;
@Component
public class FastDFSConfig {
@Resource
private ConfigurableEnvironment environment;
public Properties getProperties(String prefix) {
Properties properties = new Properties();
// 获取配置源中的所有键值对并筛选出以指定前缀开头的配置项
for (PropertySource<?> propertySource : environment.getPropertySources()) {
if (propertySource.getSource() instanceof java.util.Map) {
// 遍历所有的键值对
java.util.Map<String, Object> source = (java.util.Map<String, Object>) propertySource.getSource();
Set<String> filteredKeys = source.keySet().stream()
.filter(key -> key.startsWith(prefix)) // 过滤以prefix开头的键
.collect(Collectors.toSet());
// 将筛选后的配置项加入到Properties对象中
for (String key : filteredKeys) {
properties.setProperty(key, String.valueOf(source.get(key)));
}
}
}
return properties;
}
@Bean
public StorageClient storageClient() throws IOException, MyException {
Properties props = getProperties("fastdfs.");
ClientGlobal.initByProperties(props);
TrackerClient tracker = new TrackerClient();
TrackerServer trackerServer = tracker.getTrackerServer();
StorageServer storageServer = null;
return new StorageClient(trackerServer, storageServer);
}
}

View File

@ -1,7 +1,8 @@
package com.upchina.common.controller;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.StrUtil;
import com.upchina.common.result.CommonResult;
import com.upchina.common.util.CodecUtil;
import com.upchina.common.vo.UploadVO;
@ -10,7 +11,8 @@ import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import org.apache.commons.io.FilenameUtils;
import org.csource.common.MyException;
import org.csource.fastdfs.StorageClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
@ -22,6 +24,8 @@ import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.Arrays;
import java.util.stream.Collectors;
@Api(tags = "文件接口")
@RestController
@ -29,7 +33,7 @@ import java.io.IOException;
public class FileController {
@Resource
private FastFileStorageClient storageClient;
private StorageClient storageClient;
@Value("${file.domain.prefix}")
String domainPrefix;
@ -40,14 +44,15 @@ public class FileController {
@ApiOperation("上传")
@PostMapping("/upload")
public CommonResult<UploadVO> upload(@Parameter(content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA_VALUE))
@RequestPart("file") @Validated @ApiParam(required = true) MultipartFile file) throws IOException {
StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()), null);
String path = storePath.getFullPath();
@RequestPart("file") @Validated @ApiParam(required = true) MultipartFile file) throws IOException, MyException {
byte[] bytes = IoUtil.readBytes(file.getInputStream());
String[] results = storageClient.upload_file(bytes, FileNameUtil.getSuffix(file.getOriginalFilename()), null);
String path = Arrays.stream(results).filter(StrUtil::isNotBlank).collect(Collectors.joining("/"));
String fullPath = domainPrefix + path;
// 使用nginx
String resizePath = domainResizePrefix + path;
// md5用于文件排重
String md5 = CodecUtil.md5(file.getBytes());
String md5 = CodecUtil.md5(bytes);
return CommonResult.success(new UploadVO(fullPath, resizePath, md5));
}

View File

@ -8,14 +8,11 @@ des:
key: upchina2
file:
domain:
prefix: https://advisorimg.test.upchina.com/
resizePrefix: https://advisorimg.test.upchina.com/resize/
prefix: http://47.96.178.171:8080/
resizePrefix: http://47.96.178.171:8080/resize/
hazelcast:
members: 127.0.0.1:5709 #缓存集群的ip端口号
serverPort: 5709 #自己作为缓存服务器监听的端口号
taf:
servant:
advisorServant: DemoVideoDev.AdvisorServer.AdvisorObj@tcp -h 127.0.0.1 -t 60000 -p 45600
scheduledEnable: false
cron:
saveVideoCount: "10 * * * * ?" #从cache刷新视频播放量到DB 每分钟的第10s执行
@ -42,21 +39,21 @@ sale:
video:
finishReadRatio: 0.9 #计算视频完播率(完成人数/总人数)大于等于该值即未完成观看
websocket:
brokerHost: ws://localhost:56700/tgim
brokerHost: ws://localhost:8080/tgim
aes:
key: ew0ov3n1xurvhlhl
iv: gbb9qknndntteqc1
resizeUrl:
main: http://lczqvideodev.test.upchina.com/s/ #生产配置 http://s.upchina.com/s/
original: http://lczqvideodev.test.upchina.com/syzbh5/videoPlay
main: http://8.138.144.54:8080/s/ #生产配置 http://s.upchina.com/s/
original: http://8.138.144.54:8080/syzbh5/videoPlay
urlMain: /videoPlay?id=
shortVideoUrl: /shotVideoPlay?id=
pc:
courseRecommendSize: 5
url:
liveUrl: http://lczqvideodev.test.upchina.com/syzbpc/videoDetail?id=%d&courseId=%d
liveUrl: http://8.138.144.54:8080/syzbpc/videoDetail?id=%d&courseId=%d
app:
url:
liveUrl: https://lczqvideodev.test.upchina.com/syzbh5/videoPlay?id=%d
advisorListUrl: https://lczqvideodev.test.upchina.com/syzbh5/videoList?advisorId=%d
deptListUrl: https://lczqvideodev.test.upchina.com/syzbh5/videoList?deptId=%s
liveUrl: https://8.138.144.54:8080/syzbh5/videoPlay?id=%d
advisorListUrl: https://8.138.144.54:8080/syzbh5/videoList?advisorId=%d
deptListUrl: https://8.138.144.54:8080/syzbh5/videoList?deptId=%s

View File

@ -1,8 +1,13 @@
fdfs:
connectTimeout: 600
soTimeout: 1500
trackerList:
- 172.16.8.199:22122
fastdfs:
connect_timeout_in_seconds: 10
network_timeout_in_seconds: 30
charset: UTF-8
tracker_servers: 47.96.178.171:22122
connection_pool:
enabled: true
max_count_per_entry: 500
max_idle_time: 3600
max_wait_time_in_ms: 1000
mybatis-plus:
configuration:
call-setters-on-nulls: true #如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段