|
@@ -136,6 +136,8 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
|
|
|
private Boolean isNewWxMerchant;
|
|
private Boolean isNewWxMerchant;
|
|
|
private static final String registeredRealLink = "/pages_course/register.html?link=";
|
|
private static final String registeredRealLink = "/pages_course/register.html?link=";
|
|
|
|
|
|
|
|
|
|
+ private static final BigDecimal HUNDRED = new BigDecimal("100");
|
|
|
|
|
+
|
|
|
private static final String REDIS_KEY_PREFIX = "red_packet_config:";
|
|
private static final String REDIS_KEY_PREFIX = "red_packet_config:";
|
|
|
|
|
|
|
|
@Autowired
|
|
@Autowired
|
|
@@ -1325,68 +1327,95 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
|
|
|
trafficLog.setCreateTime(new Date());
|
|
trafficLog.setCreateTime(new Date());
|
|
|
BeanUtils.copyProperties(param, trafficLog);
|
|
BeanUtils.copyProperties(param, trafficLog);
|
|
|
|
|
|
|
|
- Long fileSize = 0L;
|
|
|
|
|
- if (ObjectUtil.isNotEmpty(param.getIsPublic()) && param.getIsPublic().equals(0)) {
|
|
|
|
|
- FsUserVideo video = fsUserVideoMapper.selectFsUserVideoByVideoId(String.valueOf(param.getVideoId()));
|
|
|
|
|
- if (video == null) {
|
|
|
|
|
- return R.error("视频不存在");
|
|
|
|
|
- }
|
|
|
|
|
- // 优先从Redis缓存获取文件大小
|
|
|
|
|
- String fileSizeRedisKey = "public:course:video:fileSize:" + param.getVideoId();
|
|
|
|
|
- String cachedFileSize = redisCache.getCacheObject(fileSizeRedisKey);
|
|
|
|
|
- if (StringUtils.isNotEmpty(cachedFileSize)) {
|
|
|
|
|
- fileSize = Long.parseLong(cachedFileSize);
|
|
|
|
|
- } else if (StringUtils.isNotEmpty(video.getUrl())) {
|
|
|
|
|
- // 缓存未命中,通过视频URL的HEAD请求获取文件大小
|
|
|
|
|
- try {
|
|
|
|
|
- java.net.HttpURLConnection conn = (java.net.HttpURLConnection) new java.net.URL(video.getUrl()).openConnection();
|
|
|
|
|
- conn.setRequestMethod("HEAD");
|
|
|
|
|
- conn.setConnectTimeout(5000);
|
|
|
|
|
- conn.setReadTimeout(5000);
|
|
|
|
|
- int contentLength = conn.getContentLength();
|
|
|
|
|
- conn.disconnect();
|
|
|
|
|
- if (contentLength > 0) {
|
|
|
|
|
- fileSize = (long) contentLength;
|
|
|
|
|
- // 写入Redis缓存,7天过期
|
|
|
|
|
- redisCache.setCacheObject(fileSizeRedisKey, String.valueOf(fileSize), 7, java.util.concurrent.TimeUnit.DAYS);
|
|
|
|
|
- }
|
|
|
|
|
- } catch (Exception ex) {
|
|
|
|
|
- logger.warn("【公开课】通过URL获取文件大小失败, videoId: {}, url: {}, error: {}", param.getVideoId(), video.getUrl(), ex.getMessage());
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }else {
|
|
|
|
|
- FsUserCourseVideo video = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(param.getVideoId());
|
|
|
|
|
- if (video == null) {
|
|
|
|
|
- return R.error("视频不存在");
|
|
|
|
|
- }
|
|
|
|
|
- fileSize = video.getFileSize();
|
|
|
|
|
-// Company company = companyMapper.selectCompanyById(param.getCompanyId());
|
|
|
|
|
-// if (company == null) {
|
|
|
|
|
-// return R.error("公司不存在");
|
|
|
|
|
-// }
|
|
|
|
|
- FsUserCourse fsUserCourse = fsUserCourseMapper.selectFsUserCourseByCourseId(param.getCourseId());
|
|
|
|
|
- if (fsUserCourse != null) {
|
|
|
|
|
- trafficLog.setProjectId(fsUserCourse.getProject());
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ long fileSize = getVideoFileSize(param);
|
|
|
|
|
+ if (fileSize < 0) {
|
|
|
|
|
+ return R.error("视频不存在");
|
|
|
}
|
|
}
|
|
|
|
|
+ setProjectIdIfNeeded(param, trafficLog);
|
|
|
|
|
|
|
|
- BigDecimal result = param.getBufferRate().divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP);
|
|
|
|
|
- BigDecimal longAsBigDecimal = BigDecimal.valueOf(fileSize);
|
|
|
|
|
- long roundedResult = result.multiply(longAsBigDecimal).setScale(0, RoundingMode.HALF_UP).longValue();
|
|
|
|
|
- trafficLog.setInternetTraffic(roundedResult);
|
|
|
|
|
|
|
+ // 计算流量 = bufferRate / 100 * fileSize
|
|
|
|
|
+ long internetTraffic = param.getBufferRate()
|
|
|
|
|
+ .multiply(BigDecimal.valueOf(fileSize))
|
|
|
|
|
+ .divide(HUNDRED, 4, RoundingMode.HALF_UP)
|
|
|
|
|
+ .setScale(0, RoundingMode.HALF_UP)
|
|
|
|
|
+ .longValue();
|
|
|
|
|
+ trafficLog.setInternetTraffic(internetTraffic);
|
|
|
|
|
|
|
|
if (StringUtils.isNotEmpty(trafficLog.getUuId())) {
|
|
if (StringUtils.isNotEmpty(trafficLog.getUuId())) {
|
|
|
fsPublicCourseTrafficLogMapper.insertOrUpdateTrafficLog(trafficLog);
|
|
fsPublicCourseTrafficLogMapper.insertOrUpdateTrafficLog(trafficLog);
|
|
|
-// asyncDeductPublicCourseTraffic(company, trafficLog);
|
|
|
|
|
}
|
|
}
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
- e.printStackTrace();
|
|
|
|
|
logger.error("【公开课插入或更新流量失败】参数: {}, 错误信息:{}", param, e.getMessage(), e);
|
|
logger.error("【公开课插入或更新流量失败】参数: {}, 错误信息:{}", param, e.getMessage(), e);
|
|
|
return R.error();
|
|
return R.error();
|
|
|
}
|
|
}
|
|
|
return R.ok();
|
|
return R.ok();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取视频文件大小
|
|
|
|
|
+ * 公开课视频(isPublic=0):从FsUserVideo获取,优先Redis缓存,未命中则HEAD请求并缓存
|
|
|
|
|
+ * 非公开课视频:从FsUserCourseVideo直接获取fileSize
|
|
|
|
|
+ * @return 文件大小,-1表示视频不存在
|
|
|
|
|
+ */
|
|
|
|
|
+ private long getVideoFileSize(FsUserCourseVideoFinishUParam param) {
|
|
|
|
|
+ if (ObjectUtil.isNotEmpty(param.getIsPublic()) && param.getIsPublic().equals(0)) {
|
|
|
|
|
+ FsUserVideo video = fsUserVideoMapper.selectFsUserVideoByVideoId(String.valueOf(param.getVideoId()));
|
|
|
|
|
+ if (video == null) {
|
|
|
|
|
+ return -1L;
|
|
|
|
|
+ }
|
|
|
|
|
+ return getPublicVideoFileSize(param.getVideoId(), video.getUrl());
|
|
|
|
|
+ } else {
|
|
|
|
|
+ FsUserCourseVideo video = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(param.getVideoId());
|
|
|
|
|
+ if (video == null) {
|
|
|
|
|
+ return -1L;
|
|
|
|
|
+ }
|
|
|
|
|
+ return video.getFileSize() != null ? video.getFileSize() : 0L;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取公开课视频文件大小,优先Redis缓存
|
|
|
|
|
+ */
|
|
|
|
|
+ private long getPublicVideoFileSize(Long videoId, String videoUrl) {
|
|
|
|
|
+ String fileSizeRedisKey = "public:course:video:fileSize:" + videoId;
|
|
|
|
|
+ String cachedFileSize = redisCache.getCacheObject(fileSizeRedisKey);
|
|
|
|
|
+ if (StringUtils.isNotEmpty(cachedFileSize)) {
|
|
|
|
|
+ return Long.parseLong(cachedFileSize);
|
|
|
|
|
+ }
|
|
|
|
|
+ // 缓存未命中,通过视频URL的HEAD请求获取文件大小
|
|
|
|
|
+ if (StringUtils.isEmpty(videoUrl)) {
|
|
|
|
|
+ return 0L;
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ java.net.HttpURLConnection conn = (java.net.HttpURLConnection) new java.net.URL(videoUrl).openConnection();
|
|
|
|
|
+ conn.setRequestMethod("HEAD");
|
|
|
|
|
+ conn.setConnectTimeout(5000);
|
|
|
|
|
+ conn.setReadTimeout(5000);
|
|
|
|
|
+ int contentLength = conn.getContentLength();
|
|
|
|
|
+ conn.disconnect();
|
|
|
|
|
+ if (contentLength > 0) {
|
|
|
|
|
+ redisCache.setCacheObject(fileSizeRedisKey, String.valueOf(contentLength), 7, java.util.concurrent.TimeUnit.DAYS);
|
|
|
|
|
+ return contentLength;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception ex) {
|
|
|
|
|
+ logger.warn("【公开课】通过URL获取文件大小失败, videoId: {}, url: {}, error: {}", videoId, videoUrl, ex.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0L;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 非公开课时设置projectId
|
|
|
|
|
+ */
|
|
|
|
|
+ private void setProjectIdIfNeeded(FsUserCourseVideoFinishUParam param, FsPublicCourseTrafficLog trafficLog) {
|
|
|
|
|
+ if (ObjectUtil.isNotEmpty(param.getIsPublic()) && param.getIsPublic().equals(0)) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ FsUserCourse fsUserCourse = fsUserCourseMapper.selectFsUserCourseByCourseId(param.getCourseId());
|
|
|
|
|
+ if (fsUserCourse != null) {
|
|
|
|
|
+ trafficLog.setProjectId(fsUserCourse.getProject());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// public void asyncDeductPublicCourseTraffic(Company company, FsPublicCourseTrafficLog trafficLog) {
|
|
// public void asyncDeductPublicCourseTraffic(Company company, FsPublicCourseTrafficLog trafficLog) {
|
|
|
// try {
|
|
// try {
|
|
|
// FsPublicCourseTrafficLog existingLog = fsPublicCourseTrafficLogMapper.selectFsPublicCourseTrafficLogByUuId(trafficLog.getUuId());
|
|
// FsPublicCourseTrafficLog existingLog = fsPublicCourseTrafficLogMapper.selectFsPublicCourseTrafficLogByUuId(trafficLog.getUuId());
|