Parcourir la source

download-proxy

xf il y a 1 an
Parent
commit
220b042187

+ 134 - 128
src/Hotline.Api/Controllers/FileController.cs

@@ -1,149 +1,155 @@
-using Hotline.File;
-using Hotline.Orders;
-using Hotline.Permissions;
-using Hotline.Repository.SqlSugar.Extensions;
-using Hotline.Settings.TimeLimits;
+using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Settings;
 using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.File;
-using Hotline.Share.Dtos.Order;
-using Hotline.Share.Enums.Order;
 using MapsterMapper;
 using Microsoft.AspNetCore.Mvc;
 using XF.Domain.Authentications;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
-using XF.Utility.EnumExtensions;
 using Hotline.Caching.Interfaces;
 
 namespace Hotline.Api.Controllers
 {
-	public class FileController : BaseController
-	{
-		private readonly ISessionContext _sessionContext;
-		private readonly IMapper _mapper;
-		private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
-		private readonly IRepository<File.File> _fileRepository;
+    public class FileController : BaseController
+    {
+        private readonly ISessionContext _sessionContext;
+        private readonly IMapper _mapper;
+        private readonly ISystemDicDataCacheManager _sysDicDataCacheManager;
+        private readonly IRepository<File.File> _fileRepository;
 
-		public FileController(
-			ISessionContext sessionContext,
-			IMapper mapper,
-			ISystemDicDataCacheManager sysDicDataCacheManager,
-			IRepository<File.File> fileRepository
-			)
-		{
-			_sessionContext = sessionContext;
-			_mapper = mapper;
-			_sysDicDataCacheManager = sysDicDataCacheManager;
-			_fileRepository = fileRepository;
-		}
-		#region 附件管理
-		/// <summary>
-		/// 新增附件
-		/// </summary>
-		/// <param name="dtos"></param>
-		/// <returns></returns>
-		[HttpPost]
-		public async Task Add([FromBody] List<FileDto> dtos)
-		{
-			List<File.File> files = new List<File.File>();
-			foreach (var dto in dtos)
-			{
-				if (string.IsNullOrEmpty(dto.Key))
-					throw UserFriendlyException.SameMessage("请上传附件关联Key");
+        public FileController(
+            ISessionContext sessionContext,
+            IMapper mapper,
+            ISystemDicDataCacheManager sysDicDataCacheManager,
+            IRepository<File.File> fileRepository
+            )
+        {
+            _sessionContext = sessionContext;
+            _mapper = mapper;
+            _sysDicDataCacheManager = sysDicDataCacheManager;
+            _fileRepository = fileRepository;
+        }
+        #region 附件管理
+        /// <summary>
+        /// 新增附件
+        /// </summary>
+        /// <param name="dtos"></param>
+        /// <returns></returns>
+        [HttpPost]
+        public async Task Add([FromBody] List<FileDto> dtos)
+        {
+            List<File.File> files = new List<File.File>();
+            foreach (var dto in dtos)
+            {
+                if (string.IsNullOrEmpty(dto.Key))
+                    throw UserFriendlyException.SameMessage("请上传附件关联Key");
 
-				var model = _mapper.Map<File.File>(dto);
-				model.OrgName = _sessionContext.OrgName;
-				model.OrgId = _sessionContext.OrgId;
-				model.UserId = _sessionContext.UserId;
-				model.UserName = _sessionContext.UserName;
-				files.Add(model);
-			}
-			await _fileRepository.AddRangeAsync(files, HttpContext.RequestAborted);
-		}
+                var model = _mapper.Map<File.File>(dto);
+                model.OrgName = _sessionContext.OrgName;
+                model.OrgId = _sessionContext.OrgId;
+                model.UserId = _sessionContext.UserId;
+                model.UserName = _sessionContext.UserName;
+                files.Add(model);
+            }
+            await _fileRepository.AddRangeAsync(files, HttpContext.RequestAborted);
+        }
 
-		/// <summary>
-		/// 删除附件
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[HttpDelete]
-		public async Task Delete([FromBody] DeleteFileDto dto)
-		{
-			foreach (var Id in dto.Ids)
-			{
-				await _fileRepository.RemoveAsync(x=>x.Id == Id);
-			}
-		}
+        /// <summary>
+        /// 删除附件
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpDelete]
+        public async Task Delete([FromBody] DeleteFileDto dto)
+        {
+            foreach (var Id in dto.Ids)
+            {
+                await _fileRepository.RemoveAsync(x => x.Id == Id);
+            }
+        }
 
-		/// <summary>
-		/// 更新附件
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[HttpPut]
-		public async Task Update([FromBody] UpdateFileDto dto)
-		{
-			//验证工单是否可以申请
-			var file = await _fileRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
-			if (file is null)
-				throw UserFriendlyException.SameMessage("无效附件");
-			_mapper.Map(dto, file);
-			file.OrgName = _sessionContext.OrgName;
-			file.OrgId = _sessionContext.OrgId;
-			file.UserId = _sessionContext.UserId;
-			file.UserName = _sessionContext.UserName;
-			await _fileRepository.UpdateAsync(file, HttpContext.RequestAborted);
-		}
+        /// <summary>
+        /// 更新附件
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpPut]
+        public async Task Update([FromBody] UpdateFileDto dto)
+        {
+            //验证工单是否可以申请
+            var file = await _fileRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
+            if (file is null)
+                throw UserFriendlyException.SameMessage("无效附件");
+            _mapper.Map(dto, file);
+            file.OrgName = _sessionContext.OrgName;
+            file.OrgId = _sessionContext.OrgId;
+            file.UserId = _sessionContext.UserId;
+            file.UserName = _sessionContext.UserName;
+            await _fileRepository.UpdateAsync(file, HttpContext.RequestAborted);
+        }
 
-		/// <summary>
-		/// 获取附件列表
-		/// </summary>
-		/// <param name="dto"></param>
-		/// <returns></returns>
-		[HttpGet("list")]
-		public async Task<PagedDto<File.File>> List([FromQuery] FileListDto dto)
-		{
-			var (total, items) = await _fileRepository.Queryable()
-				.WhereIF(!string.IsNullOrEmpty(dto.Name), x => x.Name.Contains(dto.Name))
-				.WhereIF(!string.IsNullOrEmpty(dto.Key), x => x.Key == dto.Key)
-				.WhereIF(!string.IsNullOrEmpty(dto.Type), x => x.Type == dto.Type)
-				.WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.OrgName.Contains(dto.OrgName))
-				.WhereIF(dto.Publicity > 0, x => x.Publicity == dto.Publicity)
-				.WhereIF(!string.IsNullOrEmpty(dto.Classify), x => x.Classify == dto.Classify)
-				.WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart)
-				.WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
-				.OrderByDescending(x => x.CreationTime)
-				.ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
-			return new PagedDto<File.File>(total, items);
-		}
+        /// <summary>
+        /// 获取附件列表
+        /// </summary>
+        /// <param name="dto"></param>
+        /// <returns></returns>
+        [HttpGet("list")]
+        public async Task<PagedDto<File.File>> List([FromQuery] FileListDto dto)
+        {
+            var (total, items) = await _fileRepository.Queryable()
+                .WhereIF(!string.IsNullOrEmpty(dto.Name), x => x.Name.Contains(dto.Name))
+                .WhereIF(!string.IsNullOrEmpty(dto.Key), x => x.Key == dto.Key)
+                .WhereIF(!string.IsNullOrEmpty(dto.Type), x => x.Type == dto.Type)
+                .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.OrgName.Contains(dto.OrgName))
+                .WhereIF(dto.Publicity > 0, x => x.Publicity == dto.Publicity)
+                .WhereIF(!string.IsNullOrEmpty(dto.Classify), x => x.Classify == dto.Classify)
+                .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart)
+                .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
+                .OrderByDescending(x => x.CreationTime)
+                .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
+            return new PagedDto<File.File>(total, items);
+        }
 
-		/// <summary>
-		/// 获取附件实体
-		/// </summary>
-		/// <param name="id"></param>
-		/// <returns></returns>
-		[HttpGet("{id}")]
-		public async Task<File.File> Entity(string id)
-		{
-			return await _fileRepository.Queryable()
-				.FirstAsync(x => x.Id == id);
-		}
+        /// <summary>
+        /// 获取附件实体
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [HttpGet("{id}")]
+        public async Task<File.File> Entity(string id)
+        {
+            return await _fileRepository.Queryable()
+                .FirstAsync(x => x.Id == id);
+        }
 
 
-		/// <summary>
-		/// 获取附件分类
-		/// </summary>
-		/// <returns></returns>
-		[HttpGet("classify")]
-		public Task<object> FileClassify()
-		{
-			var rsp = new
-			{
-				FileClassify =  _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.FileClassify),
-			};
-			return Task.FromResult<object>(rsp);
-		}
-		#endregion
-	}
+        /// <summary>
+        /// 获取附件分类
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("classify")]
+        public Task<object> FileClassify()
+        {
+            var rsp = new
+            {
+                FileClassify = _sysDicDataCacheManager.GetSysDicDataCache(SysDicTypeConsts.FileClassify),
+            };
+            return Task.FromResult<object>(rsp);
+        }
+        #endregion
+
+        /// <summary>
+        /// 下载(代理模式)
+        /// </summary>
+        [HttpGet("download-proxy")]
+        public async Task<IActionResult> DownloadProxy([FromServices] IHttpClientFactory clientFactory, string path)
+        {
+            using var client = clientFactory.CreateClient();
+            using var responseMessage = await client.GetAsync(path, HttpContext.RequestAborted);
+            responseMessage.EnsureSuccessStatusCode();
+            await using var stream = await responseMessage.Content.ReadAsStreamAsync(HttpContext.RequestAborted);
+            return File(stream, responseMessage?.Content?.Headers?.ContentType?.MediaType);
+        }
+    }
 }

+ 1 - 21
src/Hotline.Api/Controllers/IPPbxController.cs

@@ -274,32 +274,12 @@ namespace Hotline.Api.Controllers
         {
             _logger.LogInformation($"收到通话记录结果回传:{JsonConvert.SerializeObject(dto)}");
 
-            var recordsettings = _systemSettingCacheManager.GetSetting(SettingConstants.TapeAddress);
-            var downrecordsettings = _systemSettingCacheManager.GetSetting(SettingConstants.DownTapeAddress);
-
             var model = _mapper.Map<TrCallRecord>(dto);
             model.Duration = 0;
             model.RingTimes = 0;
             model.QueueTims = 0;
             model.OnState = Share.Enums.CallCenter.EOnState.NoOn;
-            try
-            {
-                //录音地址替换
-                if (!string.IsNullOrEmpty(recordsettings?.SettingValue[0]) && !string.IsNullOrEmpty(recordsettings?.SettingValue[1]) && !string.IsNullOrEmpty(model.RecordingFileUrl))
-                {
-                    model.RecordingFileUrl = model.RecordingFileUrl.Replace(recordsettings?.SettingValue[0], recordsettings?.SettingValue[1]);
-                }
-            }
-            catch{}
-            try
-            {
-                //下载地址替换
-                if (!string.IsNullOrEmpty(downrecordsettings?.SettingValue[0]) && !string.IsNullOrEmpty(downrecordsettings?.SettingValue[1]) && !string.IsNullOrEmpty(model.RecordingFileUrl))
-                {
-                    model.DownRecordingFileUrl = model.RecordingFileUrl.Replace(downrecordsettings?.SettingValue[0], downrecordsettings?.SettingValue[1]);
-                }
-            }
-            catch{}
+            
             //计算通话时长
             if (model.AnsweredTime != null)
             {

+ 16 - 8
src/Hotline.Application/Mappers/CallMapperConfigs.cs

@@ -23,7 +23,7 @@ namespace Hotline.Application.Mappers
                 .Map(d => d.CallAccept, x => x.call_accept)
                 .Map(d => d.CPN, x => x.caller_id_number)
                 .Map(d => d.CPNName, x => x.caller_id_name)
-                .Map(d=>d.CDPN,x=>x.destination_number)
+                .Map(d => d.CDPN, x => x.destination_number)
                 .Map(d => d.RecordingFileUrl, x => x.recording_file_url)
                 .Map(d => d.Gateway, x => x.gateway)
                 .Map(d => d.OtherStr, x => x.other_str)
@@ -33,18 +33,26 @@ namespace Hotline.Application.Mappers
                 .Map(d => d.BatchAccept, x => x.batch_accept)
                 .Map(d => d.IvrDtmf, x => x.ivr_dtmf)
                 .Map(d => d.DtmfType, x => x.dtmf_type)
-                .AfterMapping((s, d) =>{d.CreatedTime = DateTime.Parse(s.created_time);})
-                .AfterMapping((s,d) =>{d.AnsweredTime = FormatDateTime(s.answered_time);})
+                .AfterMapping((s, d) => { d.CreatedTime = DateTime.Parse(s.created_time); })
+                .AfterMapping((s, d) => { d.AnsweredTime = FormatDateTime(s.answered_time); })
                 .AfterMapping((s, d) => { d.OverTime = DateTime.Parse(s.over_time); })
                 .AfterMapping((s, d) => { d.BeginIvrTime = FormatDateTime(s.beginIvrTime); })
                 .AfterMapping((s, d) => { d.EndIvrTime = FormatDateTime(s.endIvrTime); })
                 .AfterMapping((s, d) => { d.BeginQueueTime = FormatDateTime(s.beginQueueTime); })
                 .AfterMapping((s, d) => { d.EndQueueTime = FormatDateTime(s.endQueueTime); })
                 .AfterMapping((s, d) => { d.BeginRingTime = FormatDateTime(s.beginRingTime); })
-                .AfterMapping((s, d) => { d.EndRingTimg = FormatDateTime(s.endRingTime); });
-            
-          
-                
+                .AfterMapping((s, d) => { d.EndRingTimg = FormatDateTime(s.endRingTime); })
+                .AfterMapping((s, d) =>
+                {
+                    if (string.IsNullOrEmpty(s.recording_file_url)) return;
+                    var uri = new Uri(s.recording_file_url);
+                    d.RecordingBaseAddress = $"{uri.Scheme}://{uri.Host}:{uri.Port}";
+                    d.RecordingAbsolutePath = uri.AbsolutePath;
+                })
+                ;
+
+
+
             config.ForType<ReceiveCallEvaluateDto, TrCallEvaluate>()
                 .Map(d => d.Dtmf, x => x.dtmf)
                 .Map(d => d.CallAccept, x => x.call_accept)
@@ -53,7 +61,7 @@ namespace Hotline.Application.Mappers
 
         private DateTime? FormatDateTime(string? time)
         {
-            if(string.IsNullOrEmpty(time)) return null;
+            if (string.IsNullOrEmpty(time)) return null;
 
             try
             {

+ 3 - 4
src/Hotline/CallCenter/Calls/TrCallRecord.cs

@@ -12,15 +12,14 @@ namespace Hotline.CallCenter.Calls
         /// IPPBX用户名
         /// </summary>
         public string User { get; set; }
+
         /// <summary>
         /// 可直接访问的通话录音地址
         /// </summary>
         public string? RecordingFileUrl { get; set; }
 
-        /// <summary>
-        /// 通话录音下载地址
-        /// </summary>
-        public string? DownRecordingFileUrl { get; set; }
+        public string? RecordingBaseAddress { get; set; }
+        public string? RecordingAbsolutePath { get; set; }
 
         /// <summary>
         /// 呼叫方向