修改
This commit is contained in:
parent
73d393b436
commit
d0d4e37526
@ -3,7 +3,6 @@ package com.ycwl.basic.controller.pc;
|
||||
import com.ycwl.basic.model.pc.broker.entity.BrokerEntity;
|
||||
import com.ycwl.basic.model.pc.broker.req.BrokerRecordReqQuery;
|
||||
import com.ycwl.basic.model.pc.broker.req.BrokerReqQuery;
|
||||
import com.ycwl.basic.model.pc.broker.resp.BrokerRecordRespVO;
|
||||
import com.ycwl.basic.model.pc.broker.resp.BrokerRespVO;
|
||||
import com.ycwl.basic.model.pc.broker.resp.DailySummaryRespVO;
|
||||
import com.ycwl.basic.service.pc.BrokerRecordService;
|
||||
@ -131,7 +130,7 @@ public class BrokerController {
|
||||
try {
|
||||
WxMpUtil.generateWXAQRCode(appId, appSecret, appState, path, filePath);
|
||||
File file = new File(filePath);
|
||||
String s = adapter.uploadFile(file, filePath);
|
||||
String s = adapter.uploadFile(null, file, filePath);
|
||||
file.delete();
|
||||
adapter.setAcl(StorageAcl.PUBLIC_READ, filePath);
|
||||
return ApiResponse.success(s);
|
||||
|
@ -121,7 +121,7 @@ public class ScenicController {
|
||||
try {
|
||||
WxMpUtil.generateWXAQRCode(appId, appSecret, appState, path, filePath);
|
||||
File file = new File(filePath);
|
||||
String s = adapter.uploadFile(file, filePath);
|
||||
String s = adapter.uploadFile(null, file, filePath);
|
||||
file.delete();
|
||||
adapter.setAcl(StorageAcl.PUBLIC_READ, filePath);
|
||||
return ApiResponse.success(s);
|
||||
|
@ -0,0 +1,75 @@
|
||||
package com.ycwl.basic.controller.proxy;
|
||||
|
||||
import com.ycwl.basic.annotation.IgnoreToken;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
public class ProxyController {
|
||||
@IgnoreToken
|
||||
@RequestMapping(value = "/proxy", method = RequestMethod.GET)
|
||||
public void proxy(@RequestParam(value = "url") String url,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response) throws IOException {
|
||||
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
||||
url = "http://" + url; // 或根据业务逻辑选择默认协议
|
||||
}
|
||||
|
||||
// 新增User-Agent检测逻辑
|
||||
String userAgent = request.getHeader("User-Agent");
|
||||
if (userAgent != null && userAgent.contains("Lavf/")) {
|
||||
response.sendRedirect(url);
|
||||
return;
|
||||
}
|
||||
// 创建HTTP连接
|
||||
URL urlObj = new URL(url);
|
||||
HttpURLConnection connection = (HttpURLConnection) urlObj.openConnection();
|
||||
|
||||
// 设置请求方法和请求头
|
||||
connection.setRequestMethod("GET");
|
||||
for (Enumeration<String> headers = request.getHeaderNames(); headers.hasMoreElements();) {
|
||||
String headerName = headers.nextElement();
|
||||
connection.addRequestProperty(headerName, request.getHeader(headerName));
|
||||
}
|
||||
|
||||
// 处理响应
|
||||
int responseCode = connection.getResponseCode();
|
||||
response.setStatus(responseCode);
|
||||
|
||||
// 转发响应头
|
||||
Map<String, List<String>> headerFields = connection.getHeaderFields();
|
||||
for (Map.Entry<String, List<String>> entry : headerFields.entrySet()) {
|
||||
if (entry.getKey() != null) {
|
||||
for (String value : entry.getValue()) {
|
||||
response.addHeader(entry.getKey(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 流式传输响应体
|
||||
try (InputStream inputStream = connection.getInputStream();
|
||||
OutputStream outputStream = response.getOutputStream()) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
outputStream.write(buffer, 0, bytesRead);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@ -40,7 +40,7 @@ public class VptController {
|
||||
}
|
||||
@PostMapping("/scenic/{scenicId}/{taskId}/uploadUrl")
|
||||
public String uploadUrl(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId) {
|
||||
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
|
||||
IStorageAdapter adapter = scenicService.getScenicTmpStorageAdapter(scenicId);
|
||||
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
|
||||
String urlForUpload = adapter.getUrlForUpload(new Date(System.currentTimeMillis() + 1000 * 60 * 60), "video/mp4", filename);
|
||||
urlForUpload = urlForUpload.replace("-internal.aliyuncs.com", ".aliyuncs.com");
|
||||
@ -48,7 +48,7 @@ public class VptController {
|
||||
}
|
||||
@PostMapping("/scenic/{scenicId}/{taskId}/success")
|
||||
public ApiResponse<String> success(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId, @RequestBody FileObject fileObject) {
|
||||
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
|
||||
IStorageAdapter adapter = scenicService.getScenicTmpStorageAdapter(scenicId);
|
||||
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
|
||||
fileObject.setUrl(adapter.getUrl(filename));
|
||||
adapter.setAcl(StorageAcl.PUBLIC_READ, filename);
|
||||
|
@ -45,7 +45,7 @@ public class WvpController {
|
||||
|
||||
@PostMapping("/scenic/{scenicId}/{taskId}/uploadUrl")
|
||||
public String uploadUrl(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId) {
|
||||
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
|
||||
IStorageAdapter adapter = scenicService.getScenicTmpStorageAdapter(scenicId);
|
||||
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
|
||||
String urlForUpload = adapter.getUrlForUpload(new Date(System.currentTimeMillis() + 1000 * 60 * 60), "video/mp4", filename);
|
||||
urlForUpload = urlForUpload.replace("-internal.aliyuncs.com", ".aliyuncs.com");
|
||||
@ -53,7 +53,7 @@ public class WvpController {
|
||||
}
|
||||
@PostMapping("/scenic/{scenicId}/{taskId}/success")
|
||||
public ApiResponse<String> success(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId, @RequestBody FileObject fileObject) {
|
||||
IStorageAdapter adapter = scenicService.getScenicStorageAdapter(scenicId);
|
||||
IStorageAdapter adapter = scenicService.getScenicTmpStorageAdapter(scenicId);
|
||||
String filename = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, taskId.toString() + ".mp4");
|
||||
fileObject.setUrl(adapter.getUrl(filename));
|
||||
adapter.setAcl(StorageAcl.PUBLIC_READ, filename);
|
||||
|
@ -71,6 +71,8 @@ public class ScenicConfigEntity {
|
||||
private Float faceScoreThreshold;
|
||||
private StorageType storeType;
|
||||
private String storeConfigJson;
|
||||
private StorageType tmpStoreType;
|
||||
private String tmpStoreConfigJson;
|
||||
private BigDecimal brokerDirectRate;
|
||||
private Integer faceDetectHelperThreshold;
|
||||
|
||||
|
@ -46,8 +46,12 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -199,7 +203,20 @@ public class GoodsServiceImpl implements GoodsService {
|
||||
goodsDetailVO.setGoodsType(sourceType);
|
||||
goodsDetailVO.setSourceType(sourceType);
|
||||
goodsDetailVO.setGoodsId(sourceRespVO.getId());
|
||||
goodsDetailVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||
if (sourceRespVO.getVideoUrl() != null) {
|
||||
try {
|
||||
URL url = new URL(sourceRespVO.getVideoUrl());
|
||||
if (StringUtils.startsWith(url.getHost(), "100.64.")) {
|
||||
// 内网地址,需要代理
|
||||
goodsDetailVO.setVideoUrl("https://zhentuai.com/proxy?url=" + sourceRespVO.getVideoUrl());
|
||||
} else {
|
||||
goodsDetailVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
log.warn("url地址解析异常:{}", sourceRespVO.getVideoUrl(), e);
|
||||
goodsDetailVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||
}
|
||||
}
|
||||
goodsDetailVO.setUrl(sourceRespVO.getUrl());
|
||||
goodsDetailVO.setCreateTime(sourceRespVO.getCreateTime());
|
||||
goodsDetailVO.setIsFree(sourceRespVO.getIsFree());
|
||||
@ -430,10 +447,7 @@ public class GoodsServiceImpl implements GoodsService {
|
||||
public ApiResponse<GoodsDetailVO> sourceGoodsInfo(Long sourceId) {
|
||||
SourceRespVO sourceRespVO = sourceMapper.getById(sourceId);
|
||||
if (sourceRespVO == null) {
|
||||
sourceRespVO = sourceMapper.getById(sourceId);
|
||||
if (sourceRespVO == null) {
|
||||
return ApiResponse.fail("该视频不存在");
|
||||
}
|
||||
return ApiResponse.fail("该视频不存在");
|
||||
}
|
||||
GoodsDetailVO goodsDetailVO = new GoodsDetailVO();
|
||||
goodsDetailVO.setGoodsName("原片");
|
||||
@ -441,7 +455,20 @@ public class GoodsServiceImpl implements GoodsService {
|
||||
goodsDetailVO.setScenicName(sourceRespVO.getScenicName());
|
||||
goodsDetailVO.setGoodsType(sourceRespVO.getType());
|
||||
goodsDetailVO.setGoodsId(sourceRespVO.getId());
|
||||
goodsDetailVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||
if (sourceRespVO.getVideoUrl() != null) {
|
||||
try {
|
||||
URL url = new URL(sourceRespVO.getVideoUrl());
|
||||
if (StringUtils.startsWith(url.getHost(), "100.64.")) {
|
||||
// 内网地址,需要代理
|
||||
goodsDetailVO.setVideoUrl("https://zhentuai.com/proxy?url=" + sourceRespVO.getVideoUrl());
|
||||
} else {
|
||||
goodsDetailVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
log.warn("url地址解析异常:{}", sourceRespVO.getVideoUrl(), e);
|
||||
goodsDetailVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||
}
|
||||
}
|
||||
goodsDetailVO.setTemplateCoverUrl(sourceRespVO.getUrl());
|
||||
goodsDetailVO.setCreateTime(sourceRespVO.getCreateTime());
|
||||
return ApiResponse.success(goodsDetailVO);
|
||||
@ -522,7 +549,7 @@ public class GoodsServiceImpl implements GoodsService {
|
||||
log.error("process error", e);
|
||||
return;
|
||||
}
|
||||
String url = adapter.uploadFile(watermarkedFile, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
|
||||
String url = adapter.uploadFile(null, watermarkedFile, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
|
||||
adapter.setAcl(StorageAcl.PUBLIC_READ, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
|
||||
sourceMapper.addSourceWatermark(item.getGoodsId(), null, ImageWatermarkOperatorEnum.WATERMARK.getType(), url);
|
||||
tmpFile.add(watermarkedFile);
|
||||
@ -634,7 +661,7 @@ public class GoodsServiceImpl implements GoodsService {
|
||||
log.error("process error", e);
|
||||
return;
|
||||
}
|
||||
String url = adapter.uploadFile(watermarkedFile, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
|
||||
String url = adapter.uploadFile(null, watermarkedFile, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
|
||||
adapter.setAcl(StorageAcl.PUBLIC_READ, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
|
||||
sourceMapper.addSourceWatermark(item.getGoodsId(), face.getId(), type.getType(), url);
|
||||
tmpFile.add(watermarkedFile);
|
||||
|
@ -36,5 +36,7 @@ public interface ScenicService {
|
||||
|
||||
IStorageAdapter getScenicStorageAdapter(Long scenicId);
|
||||
|
||||
IStorageAdapter getScenicTmpStorageAdapter(Long scenicId);
|
||||
|
||||
IFaceBodyAdapter getScenicFaceBodyAdapter(Long scenicId);
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import com.ycwl.basic.service.pc.ScenicService;
|
||||
import com.ycwl.basic.service.task.TaskFaceService;
|
||||
import com.ycwl.basic.storage.StorageFactory;
|
||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||
import com.ycwl.basic.storage.exceptions.StorageUnsupportedException;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import com.ycwl.basic.utils.SnowFlakeUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -197,6 +198,7 @@ public class ScenicServiceImpl implements ScenicService {
|
||||
scenicRepository.clearCache(config.getScenicId());
|
||||
scenicFaceBodyAdapterMap.remove(config.getScenicId());
|
||||
scenicStorageAdapterMap.remove(config.getScenicId());
|
||||
scenicTmpStorageAdapterMap.remove(config.getScenicId());
|
||||
}
|
||||
|
||||
|
||||
@ -207,14 +209,37 @@ public class ScenicServiceImpl implements ScenicService {
|
||||
IStorageAdapter adapter;
|
||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
||||
if (scenicConfig != null && scenicConfig.getStoreType() != null) {
|
||||
adapter = StorageFactory.get(scenicConfig.getStoreType());
|
||||
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
|
||||
try {
|
||||
adapter = StorageFactory.get(scenicConfig.getStoreType());
|
||||
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getStoreConfigJson(), Map.class));
|
||||
} catch (StorageUnsupportedException ignored) {
|
||||
return StorageFactory.use("video");
|
||||
}
|
||||
} else {
|
||||
adapter = StorageFactory.use("video");
|
||||
}
|
||||
return adapter;
|
||||
});
|
||||
}
|
||||
private static final Map<Long, IStorageAdapter> scenicTmpStorageAdapterMap = new ConcurrentHashMap<>();
|
||||
@Override
|
||||
public IStorageAdapter getScenicTmpStorageAdapter(Long scenicId) {
|
||||
return scenicTmpStorageAdapterMap.computeIfAbsent(scenicId, (key) -> {
|
||||
IStorageAdapter adapter;
|
||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
||||
if (scenicConfig != null && scenicConfig.getTmpStoreType() != null) {
|
||||
try {
|
||||
adapter = StorageFactory.get(scenicConfig.getTmpStoreType());
|
||||
adapter.loadConfig(JSONObject.parseObject(scenicConfig.getTmpStoreConfigJson(), Map.class));
|
||||
} catch (StorageUnsupportedException ignored) {
|
||||
return getScenicStorageAdapter(scenicId);
|
||||
}
|
||||
} else {
|
||||
return getScenicStorageAdapter(scenicId);
|
||||
}
|
||||
return adapter;
|
||||
});
|
||||
}
|
||||
private static final Map<Long, IFaceBodyAdapter> scenicFaceBodyAdapterMap = new ConcurrentHashMap<>();
|
||||
@Override
|
||||
public IFaceBodyAdapter getScenicFaceBodyAdapter(Long scenicId) {
|
||||
|
@ -11,9 +11,12 @@ import com.ycwl.basic.service.pc.SourceService;
|
||||
import com.ycwl.basic.task.VideoPieceGetter;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import com.ycwl.basic.utils.SnowFlakeUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@ -32,18 +35,63 @@ public class SourceServiceImpl implements SourceService {
|
||||
public ApiResponse<PageInfo<SourceRespVO>> pageQuery(SourceReqQuery sourceReqQuery) {
|
||||
PageHelper.startPage(sourceReqQuery.getPageNum(), sourceReqQuery.getPageSize());
|
||||
List<SourceRespVO> list = sourceMapper.list(sourceReqQuery);
|
||||
list.forEach(sourceRespVO -> {
|
||||
if (sourceRespVO.getVideoUrl() != null) {
|
||||
try {
|
||||
URL url = new URL(sourceRespVO.getVideoUrl());
|
||||
if (StringUtils.startsWith(url.getHost(), "100.64.")) {
|
||||
// 内网地址,需要代理
|
||||
sourceRespVO.setVideoUrl("https://zhentuai.com/proxy?url=" + sourceRespVO.getVideoUrl());
|
||||
} else {
|
||||
sourceRespVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
sourceRespVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||
}
|
||||
}
|
||||
});
|
||||
PageInfo<SourceRespVO> pageInfo = new PageInfo<>(list);
|
||||
return ApiResponse.success(pageInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<List<SourceRespVO>> list(SourceReqQuery sourceReqQuery) {
|
||||
return ApiResponse.success(sourceMapper.list(sourceReqQuery));
|
||||
List<SourceRespVO> list = sourceMapper.list(sourceReqQuery);
|
||||
list.forEach(sourceRespVO -> {
|
||||
if (sourceRespVO.getVideoUrl() != null) {
|
||||
try {
|
||||
URL url = new URL(sourceRespVO.getVideoUrl());
|
||||
if (StringUtils.startsWith(url.getHost(), "100.64.")) {
|
||||
// 内网地址,需要代理
|
||||
sourceRespVO.setVideoUrl("https://zhentuai.com/proxy?url=" + sourceRespVO.getVideoUrl());
|
||||
} else {
|
||||
sourceRespVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
sourceRespVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||
}
|
||||
}
|
||||
});
|
||||
return ApiResponse.success(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<SourceRespVO> getById(Long id, Long userId) {
|
||||
return ApiResponse.success(sourceMapper.userGetById(id, userId));
|
||||
SourceRespVO sourceRespVO = sourceMapper.userGetById(id, userId);
|
||||
if (sourceRespVO.getVideoUrl() != null) {
|
||||
try {
|
||||
URL url = new URL(sourceRespVO.getVideoUrl());
|
||||
if (StringUtils.startsWith(url.getHost(), "100.64.")) {
|
||||
// 内网地址,需要代理
|
||||
sourceRespVO.setVideoUrl("https://zhentuai.com/proxy?url=" + sourceRespVO.getVideoUrl());
|
||||
} else {
|
||||
sourceRespVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
sourceRespVO.setVideoUrl(sourceRespVO.getVideoUrl());
|
||||
}
|
||||
}
|
||||
return ApiResponse.success(sourceRespVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -10,8 +10,6 @@ public interface TaskFaceService {
|
||||
|
||||
SearchFaceRespVo searchFace(IFaceBodyAdapter adapter, String dbName, String faceUrl, String reason);
|
||||
|
||||
String uploadFile(MultipartFile file, Long userId);
|
||||
|
||||
boolean deleteFaceSample(Long scenicId, String dbName, String entityId);
|
||||
|
||||
boolean assureFaceDb(IFaceBodyAdapter faceBodyAdapter, String dbName);
|
||||
|
@ -289,30 +289,6 @@ public class TaskFaceServiceImpl implements TaskFaceService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uploadFile(MultipartFile file, Long userId) {
|
||||
if (file.isEmpty()) {
|
||||
throw new RuntimeException("文件不存在!");
|
||||
}
|
||||
String originalFilename = file.getOriginalFilename();
|
||||
//获取文件名后缀
|
||||
String suffix = originalFilename.split("\\.")[1];
|
||||
if ("Jpeg".equals(suffix)) {
|
||||
suffix = "jpg";
|
||||
}
|
||||
//文件储存路径
|
||||
String filePath = StorageUtil.joinPath("user-faces", DateUtils.format(new Date(),"yyyy-MM-dd"));
|
||||
// 生成文件名
|
||||
String fileName= userId + "." + suffix;
|
||||
IStorageAdapter adapter = StorageFactory.use("faces");
|
||||
try {
|
||||
return adapter.uploadFile(file.getInputStream(), filePath, fileName);
|
||||
} catch (IOException e) {
|
||||
log.error("文件上传失败!", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteFaceSample(Long scenicId, String dbName, String entityId) {
|
||||
ScenicConfigEntity scenicConfig = scenicRepository.getScenicConfig(scenicId);
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.ycwl.basic.storage.adapters;
|
||||
|
||||
import com.ycwl.basic.storage.exceptions.UploadFileFailedException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
@ -9,16 +10,17 @@ import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Date;
|
||||
|
||||
@Slf4j
|
||||
public abstract class AStorageAdapter implements IStorageAdapter {
|
||||
|
||||
@Override
|
||||
public String uploadFile(File file, String ...path) {
|
||||
public String uploadFile(String contentType, File file, String ...path) {
|
||||
if (file == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
InputStream inputStream = new FileInputStream(file);
|
||||
return uploadFile(inputStream, path);
|
||||
return uploadFile(contentType, inputStream, path);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new UploadFileFailedException("文件不存在");
|
||||
}
|
||||
@ -31,8 +33,9 @@ public abstract class AStorageAdapter implements IStorageAdapter {
|
||||
}
|
||||
try {
|
||||
InputStream inputStream = file.getInputStream();
|
||||
return uploadFile(inputStream, path);
|
||||
return uploadFile(file.getContentType(), inputStream, path);
|
||||
} catch (Exception e) {
|
||||
log.warn("文件上传失败", e);
|
||||
throw new UploadFileFailedException("文件上传失败");
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ final public class AliOssAdapter extends AStorageAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uploadFile(InputStream inputStream, String ...path) {
|
||||
public String uploadFile(String contentType, InputStream inputStream, String ...path) {
|
||||
if (inputStream == null) {
|
||||
return null;
|
||||
}
|
||||
@ -71,6 +71,9 @@ final public class AliOssAdapter extends AStorageAdapter {
|
||||
OSS ossClient = wrapper.getOSSClient();
|
||||
ObjectMetadata metadata = new ObjectMetadata();
|
||||
metadata.setContentLength(inputStream.available());
|
||||
if (StringUtils.isNotBlank(contentType)) {
|
||||
metadata.setContentType(contentType);
|
||||
}
|
||||
PutObjectRequest putObjectRequest = new PutObjectRequest(config.getBucketName(), fullPath, inputStream);
|
||||
ossClient.putObject(putObjectRequest);
|
||||
return getUrl(path);
|
||||
|
@ -55,7 +55,7 @@ public class AwsOssAdapter extends AStorageAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uploadFile(InputStream inputStream, String... path) {
|
||||
public String uploadFile(String contentType, InputStream inputStream, String... path) {
|
||||
if (inputStream == null) {
|
||||
return null;
|
||||
}
|
||||
@ -64,6 +64,9 @@ public class AwsOssAdapter extends AStorageAdapter {
|
||||
AmazonS3Client s3Client = wrapper.getS3Client();
|
||||
ObjectMetadata metadata = new ObjectMetadata();
|
||||
metadata.setContentLength(inputStream.available());
|
||||
if (StringUtils.isNotBlank(contentType)) {
|
||||
metadata.setContentType(contentType);
|
||||
}
|
||||
PutObjectRequest putObjectRequest = new PutObjectRequest(config.getBucketName(), fullPath, inputStream, metadata);
|
||||
putObjectRequest.withCannedAcl(CannedAccessControlList.PublicRead); // 设置访问权限,让所有用户都允许访问
|
||||
s3Client.putObject(putObjectRequest);
|
||||
|
@ -14,8 +14,8 @@ import java.util.Map;
|
||||
public interface IStorageAdapter {
|
||||
void loadConfig(Map<String, String> config);
|
||||
void setConfig(StorageConfig config);
|
||||
String uploadFile(InputStream inputStream, String ...path);
|
||||
String uploadFile(File file, String ...path);
|
||||
String uploadFile(String contentType, InputStream inputStream, String ...path);
|
||||
String uploadFile(String contentType, File file, String ...path);
|
||||
String uploadFile(MultipartFile file, String ...path);
|
||||
boolean deleteFile(String ...path);
|
||||
String getUrl(String ...path);
|
||||
|
@ -22,7 +22,7 @@ public class LocalStorageAdapter extends AStorageAdapter{
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uploadFile(InputStream inputStream, String... path) {
|
||||
public String uploadFile(String contentType, InputStream inputStream, String... path) {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,15 @@ package com.ycwl.basic.storage.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class StorageFileObject {
|
||||
private String path;
|
||||
private String name;
|
||||
private Long size;
|
||||
private Object rawObject;
|
||||
private Date modifyTime;
|
||||
|
||||
public String getFullPath() {
|
||||
return path + "/" + name;
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.ycwl.basic.task;
|
||||
|
||||
import cn.hutool.core.date.DateUnit;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import com.ycwl.basic.constant.StorageConstant;
|
||||
import com.ycwl.basic.facebody.adapter.IFaceBodyAdapter;
|
||||
@ -211,6 +212,12 @@ public class FaceCleaner {
|
||||
IStorageAdapter adapter = StorageFactory.use("faces");
|
||||
List<StorageFileObject> fileObjectList = adapter.listDir("user-face");
|
||||
fileObjectList.parallelStream().forEach(fileObject -> {
|
||||
if (fileObject.getModifyTime() != null) {
|
||||
// 如果是一天以内修改的,则跳过
|
||||
if (DateUtil.between(fileObject.getModifyTime(), new Date(), DateUnit.DAY) < 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(faceSampleRespVOS.parallelStream().noneMatch(faceSampleRespVO -> faceSampleRespVO.getFaceUrl().contains(fileObject.getFullPath()))){
|
||||
log.info("删除人脸文件:{}", fileObject);
|
||||
adapter.deleteFile(fileObject.getFullPath());
|
||||
@ -225,6 +232,12 @@ public class FaceCleaner {
|
||||
log.info("开始清理视频文件");
|
||||
List<StorageFileObject> fileObjectList = adapter.listDir(StorageConstant.VIDEO_PIECE_PATH);
|
||||
fileObjectList.parallelStream().forEach(fileObject -> {
|
||||
if (fileObject.getModifyTime() != null) {
|
||||
// 如果是一天以内修改的,则跳过
|
||||
if (DateUtil.between(fileObject.getModifyTime(), new Date(), DateUnit.DAY) < 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (list.parallelStream().filter(videoRespVO -> Objects.nonNull(videoRespVO.getVideoUrl())).noneMatch(videoRespVO -> videoRespVO.getVideoUrl().contains(fileObject.getFullPath()))){
|
||||
log.info("删除文件:{}", fileObject);
|
||||
adapter.deleteFile(fileObject.getFullPath());
|
||||
@ -235,6 +248,12 @@ public class FaceCleaner {
|
||||
log.info("开始清理图片文件");
|
||||
fileObjectList = adapter.listDir(StorageConstant.PHOTO_PATH);
|
||||
fileObjectList.parallelStream().forEach(fileObject -> {
|
||||
if (fileObject.getModifyTime() != null) {
|
||||
// 如果是一天以内修改的,则跳过
|
||||
if (DateUtil.between(fileObject.getModifyTime(), new Date(), DateUnit.DAY) < 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (list.parallelStream().filter(videoRespVO -> Objects.nonNull(videoRespVO.getUrl())).noneMatch(videoRespVO -> videoRespVO.getUrl().contains(fileObject.getFullPath()))){
|
||||
log.info("删除文件:{}", fileObject);
|
||||
adapter.deleteFile(fileObject.getFullPath());
|
||||
@ -252,6 +271,12 @@ public class FaceCleaner {
|
||||
log.info("开始清理视频文件");
|
||||
List<StorageFileObject> fileObjectList = adapter.listDir(StorageConstant.VLOG_PATH);
|
||||
fileObjectList.parallelStream().forEach(fileObject -> {
|
||||
if (fileObject.getModifyTime() != null) {
|
||||
// 如果是一天以内修改的,则跳过
|
||||
if (DateUtil.between(fileObject.getModifyTime(), new Date(), DateUnit.DAY) < 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (list.parallelStream().filter(videoRespVO -> Objects.nonNull(videoRespVO.getVideoUrl())).noneMatch(videoRespVO -> videoRespVO.getVideoUrl().contains(fileObject.getFullPath()))){
|
||||
log.info("删除文件:{}", fileObject);
|
||||
adapter.deleteFile(fileObject.getFullPath());
|
||||
|
@ -3,11 +3,11 @@ package com.ycwl.basic.task;
|
||||
import cn.hutool.core.thread.ThreadFactoryBuilder;
|
||||
import com.ycwl.basic.biz.OrderBiz;
|
||||
import com.ycwl.basic.biz.TaskStatusBiz;
|
||||
import com.ycwl.basic.constant.StorageConstant;
|
||||
import com.ycwl.basic.device.DeviceFactory;
|
||||
import com.ycwl.basic.device.entity.common.FileObject;
|
||||
import com.ycwl.basic.device.operator.IDeviceStorageOperator;
|
||||
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
|
||||
import com.ycwl.basic.model.pc.faceSample.resp.FaceSampleRespVO;
|
||||
import com.ycwl.basic.repository.DeviceRepository;
|
||||
import com.ycwl.basic.mapper.FaceSampleMapper;
|
||||
import com.ycwl.basic.mapper.SourceMapper;
|
||||
@ -20,9 +20,9 @@ import com.ycwl.basic.repository.TemplateRepository;
|
||||
import com.ycwl.basic.storage.StorageFactory;
|
||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||
import com.ycwl.basic.utils.SnowFlakeUtil;
|
||||
import com.ycwl.basic.utils.VideoReUploader;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
@ -65,6 +65,8 @@ public class VideoPieceGetter {
|
||||
private TemplateRepository templateRepository;
|
||||
@Autowired
|
||||
private TaskStatusBiz taskStatusBiz;
|
||||
@Autowired
|
||||
private VideoReUploader videoReUploader;
|
||||
|
||||
@Data
|
||||
public static class Task {
|
||||
@ -285,7 +287,7 @@ public class VideoPieceGetter {
|
||||
}
|
||||
log.info("视频裁切成功");
|
||||
IStorageAdapter adapter = StorageFactory.use("assets");
|
||||
url = adapter.uploadFile(outFile, "video-source", outFile.getName());
|
||||
url = adapter.uploadFile("video/mp4", outFile, StorageConstant.VIDEO_PIECE_PATH, outFile.getName());
|
||||
// 上传成功后删除文件
|
||||
outFile.delete();
|
||||
}
|
||||
@ -320,6 +322,7 @@ public class VideoPieceGetter {
|
||||
sourceMapper.addRelation(videoSource);
|
||||
}
|
||||
sourceMapper.add(sourceEntity);
|
||||
videoReUploader.addTask(sourceEntity.getVideoUrl(), sourceEntity.getId());
|
||||
} else {
|
||||
// 有原视频
|
||||
if (task.memberId != null && task.faceId != null) {
|
||||
|
@ -45,8 +45,7 @@ public class ImageUtils {
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
// TODO - implementation depends on your requirements
|
||||
return header.split(":")[0];
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
93
src/main/java/com/ycwl/basic/utils/VideoReUploader.java
Normal file
93
src/main/java/com/ycwl/basic/utils/VideoReUploader.java
Normal file
@ -0,0 +1,93 @@
|
||||
package com.ycwl.basic.utils;
|
||||
|
||||
import cn.hutool.core.thread.ThreadFactoryBuilder;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.ycwl.basic.constant.StorageConstant;
|
||||
import com.ycwl.basic.mapper.SourceMapper;
|
||||
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
|
||||
import com.ycwl.basic.service.pc.ScenicService;
|
||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||
import com.ycwl.basic.storage.utils.StorageUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class VideoReUploader {
|
||||
private static final ThreadFactory threadFactory = new ThreadFactoryBuilder()
|
||||
.setNamePrefix("Vid-ReUp-")
|
||||
.build();
|
||||
private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(8, 1024, 0L, TimeUnit.MILLISECONDS,
|
||||
new ArrayBlockingQueue<>(1024),
|
||||
threadFactory
|
||||
);
|
||||
|
||||
@Autowired
|
||||
private SourceMapper sourceMapper;
|
||||
@Autowired
|
||||
private ScenicService scenicService;
|
||||
|
||||
public void addTask(String url, Long sourceId) {
|
||||
try {
|
||||
URL _url = new URL(url);
|
||||
if (!StringUtils.startsWith(_url.getHost(), "100.64.")) {
|
||||
return;
|
||||
}
|
||||
} catch (MalformedURLException ignored) {
|
||||
return;
|
||||
}
|
||||
SourceEntity entity = sourceMapper.getEntity(sourceId);
|
||||
if (entity == null) {
|
||||
return;
|
||||
}
|
||||
if (entity.getScenicId() == null) {
|
||||
return;
|
||||
}
|
||||
if (entity.getType() != 1) {
|
||||
return;
|
||||
}
|
||||
String tmpFilePath = UUID.randomUUID().toString();
|
||||
executor.execute(() -> {
|
||||
// 先下载,后上传
|
||||
File dstFile = new File(tmpFilePath);
|
||||
log.info("下载视频:{};sourceId:{}", url, sourceId);
|
||||
long size = HttpUtil.downloadFile(url, dstFile);
|
||||
log.info("下载视频完成:{};大小:{};sourceId:{}", url, size, sourceId);
|
||||
String dstFilePath = StorageUtil.joinPath(StorageConstant.VIDEO_PIECE_PATH, entity.getId().toString() + ".mp4");
|
||||
IStorageAdapter dstAdapter = scenicService.getScenicStorageAdapter(entity.getScenicId());
|
||||
try {
|
||||
log.info("开始上传:{};sourceId:{}", dstFilePath, sourceId);
|
||||
String newUrl = dstAdapter.uploadFile("video/mp4", dstFile, dstFilePath);
|
||||
log.info("上传成功:{};sourceId:{}", newUrl, sourceId);
|
||||
SourceEntity updateEntity = new SourceEntity();
|
||||
updateEntity.setId(sourceId);
|
||||
updateEntity.setVideoUrl(newUrl);
|
||||
sourceMapper.update(updateEntity);
|
||||
} catch (Exception e) {
|
||||
log.info("上传失败:{};sourceId:{}", dstFilePath, sourceId, e);
|
||||
} finally {
|
||||
try {
|
||||
dstFile.delete();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -109,6 +109,8 @@
|
||||
face_detect_helper_threshold=#{faceDetectHelperThreshold},
|
||||
store_type=#{storeType},
|
||||
store_config_json=#{storeConfigJson},
|
||||
tmp_store_type=#{tmpStoreType},
|
||||
tmp_store_config_json=#{tmpStoreConfigJson},
|
||||
broker_direct_rate=#{brokerDirectRate},
|
||||
watermark_type=#{watermarkType},
|
||||
watermark_scenic_text=#{watermarkScenicText},
|
||||
|
Loading…
x
Reference in New Issue
Block a user