IcloudService.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. # -*- coding: utf-8 -*-
  2. """
  3. @Author : peng
  4. @Time : 2023-6-7 18:26:35
  5. @File :IcloudMeal.py
  6. """
  7. import logging
  8. import time
  9. from django.db.models import Sum, Q
  10. from django.http import HttpResponse
  11. from django.views import View
  12. from Model.models import IcloudUseDetails, IcloudService, VodBucketModel, IcloudStorageRecord, Device_Info
  13. from Object.AWS.AmazonS3Util import AmazonS3Util
  14. from Object.RedisObject import RedisObject
  15. from Object.ResponseObject import ResponseObject
  16. from Object.TokenObject import TokenObject
  17. from Ansjer.config import ACCESS_KEY_ID, SECRET_ACCESS_KEY, REGION_NAME, SERVER_DOMAIN, AWS_ACCESS_KEY_ID, \
  18. AWS_SECRET_ACCESS_KEY
  19. from Service.VodHlsService import SplitVodHlsObject
  20. logger = logging.getLogger('info')
  21. class IcloudServiceView(View):
  22. def get(self, request, *args, **kwargs):
  23. request.encoding = 'utf-8'
  24. operation = kwargs.get('operation')
  25. return self.validation(request.GET, operation, request)
  26. def post(self, request, *args, **kwargs):
  27. request.encoding = 'utf-8'
  28. operation = kwargs.get('operation')
  29. return self.validation(request.POST, operation, request)
  30. def validation(self, request_dict, operation, request):
  31. response = ResponseObject()
  32. tko = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
  33. response.lang = tko.lang
  34. user_id = tko.userID
  35. if tko.code != 0:
  36. return response.json(tko.code)
  37. if operation == 'vodUpload': # 云存上传云盘
  38. return self.vod_upload(request_dict, response, user_id)
  39. elif operation == 'getUploadUrl': # 获取s3上传地址
  40. return self.get_upload_url(request_dict, response, user_id)
  41. elif operation == 'localUpload': # 本地上传云盘
  42. return self.local_upload(request_dict, response, user_id)
  43. else:
  44. return response.json(404)
  45. @staticmethod
  46. def vod_upload(request_dict, response, user_id):
  47. """
  48. 云存上传云盘
  49. @param request_dict: 请求参数
  50. @param user_id: 用户id
  51. @request_dict uid: 设备uid
  52. @request_dict channel: 设备通道
  53. @request_dict start_time: 播放时间戳
  54. @param response: 响应对象
  55. @return: response
  56. """
  57. logger.info('开始云存转移到云盘')
  58. uid = request_dict.get('uid', None)
  59. channel = request_dict.get('channel', None)
  60. time_stamp = request_dict.get('time_stamp', None)
  61. if not all([uid, channel, time_stamp]):
  62. return response.json(444, {'error param': 'uid,channel,start_time'})
  63. device_qs = Device_Info.objects.filter(UID=uid, userID=user_id).values('NickName')
  64. if not device_qs.exists():
  65. return response.json(173)
  66. # 查询是否开通云盘
  67. use_details_qs = IcloudUseDetails.objects.filter(user_id=user_id).values('id', 'bucket_id', 'use_size')
  68. if not use_details_qs.exists():
  69. return response.json(173)
  70. use_details_id = use_details_qs[0]['id']
  71. target_bucket_id = use_details_qs[0]['bucket_id']
  72. use_size = float(use_details_qs[0]['use_size'])
  73. now_time = int(time.time())
  74. nickname = device_qs[0]['NickName']
  75. # 判断云盘是否还有容量
  76. all_size = IcloudService.objects.filter(Q(use_details_id=use_details_id), Q(use_status=0),
  77. Q(end_time__gt=now_time) | Q(end_time=0)).values(
  78. 'size').aggregate(total_size=Sum('size'))['total_size']
  79. all_size = all_size * 1024 if all_size else 0
  80. if use_size > all_size:
  81. logger.info('{}用户套餐总容量为:{},已使用容量为:{}'.format(uid, all_size, use_size))
  82. return response.json(910)
  83. split_vod_hls_obj = SplitVodHlsObject()
  84. vod_hls = split_vod_hls_obj.get_vod_hls_data(uid=uid, channel=channel, start_time=time_stamp).values(
  85. 'bucket_id', 'fg', 'sec')
  86. if not vod_hls.exists():
  87. logger.info('{}用户查无此云存:{}'.format(uid, time_stamp))
  88. return response.json(173)
  89. source_bucket_id = vod_hls[0]['bucket_id']
  90. fg = int(vod_hls[0]['fg'])
  91. sec = vod_hls[0]['sec']
  92. target_bucket_qs = VodBucketModel.objects.filter(id=target_bucket_id).values('bucket')
  93. if not target_bucket_qs.exists():
  94. return response.json(173)
  95. target_bucket_name = target_bucket_qs[0]['bucket']
  96. source_bucket_qs = VodBucketModel.objects.filter(id=source_bucket_id).values('bucket', 'region', 'mold')
  97. if not source_bucket_qs.exists():
  98. return response.json(173)
  99. bucket_region = source_bucket_qs[0]['region']
  100. source_bucket_name = source_bucket_qs[0]['bucket']
  101. mold = source_bucket_qs[0]["mold"]
  102. ts_list = []
  103. ts_size = 0
  104. try:
  105. s3_obj = AmazonS3Util(
  106. AWS_ACCESS_KEY_ID[mold],
  107. AWS_SECRET_ACCESS_KEY[mold],
  108. bucket_region
  109. )
  110. # 获取s3对象,并计算总字节
  111. for i in range(15):
  112. shift = (i + 1) * 4
  113. duration = (fg >> shift) & 0xf
  114. if duration > 0:
  115. ts_file = '{uid}/vod{channel}/{time}/ts{i}.ts'.format(uid=uid, channel=channel, time=time_stamp,
  116. i=i)
  117. ts_list.append(ts_file)
  118. ts_size += s3_obj.get_object_size(source_bucket_name, ts_file) # 获取存储对象字节,单位B
  119. ts_size = round(ts_size / 1024 / 1024, 2) # 字节转换为MB单位
  120. temp_size = ts_size + use_size
  121. if temp_size > all_size:
  122. logger.info('{}用户无空间上传,套餐容量为:{},使用容量为:{}'.format(uid, all_size, temp_size))
  123. return response.json(910)
  124. time_stamp = int(time_stamp) * 1000 # 转换单位为毫秒
  125. icloud_record_qs = IcloudStorageRecord.objects.filter(user_id=user_id, uid=uid, channel=channel,
  126. time_stamp=time_stamp,
  127. size=ts_size, file_type=1)
  128. if not icloud_record_qs.exists(): # 转移云盘,并记录上传记录,更新使用容量
  129. for source_key in ts_list:
  130. ts_name = source_key.split('/')[-1]
  131. target_key = '{user_id}/ts_file/{uid}/vod{channel}/{time}/{ts_name}'.format(user_id=user_id,
  132. uid=uid,
  133. channel=channel,
  134. time=time_stamp,
  135. ts_name=ts_name)
  136. s3_obj.copy_single_obj(source_bucket_name, source_key, target_bucket_name, target_key)
  137. IcloudStorageRecord.objects.create(user_id=user_id, uid=uid, channel=channel, time_stamp=time_stamp,
  138. nickname=nickname,
  139. sec=sec, bucket_id=target_bucket_id, fg=fg, size=ts_size,
  140. file_type=1)
  141. use_details_qs.update(use_size=temp_size)
  142. return response.json(0)
  143. else:
  144. return response.json(174)
  145. except Exception as e:
  146. logger.info('云存转移云盘异常:{}'.format(repr(e)))
  147. return response.json(500)
  148. @staticmethod
  149. def local_upload(request_dict, response, user_id):
  150. """
  151. 本地上传云盘
  152. @param request_dict: 请求参数
  153. @param user_id: 用户id
  154. @request_dict serial_number: 序列号
  155. @param response: 响应对象
  156. @return: response
  157. """
  158. logger.info('开始本地转移到云盘')
  159. uid = request_dict.get('uid', None)
  160. channel = request_dict.get('channel', None)
  161. time_stamp = request_dict.get('time_stamp', None)
  162. size = request_dict.get('size', None)
  163. file_type = request_dict.get('file_type', None)
  164. sec = request_dict.get('sec', 0)
  165. if not all([uid, channel, time_stamp, size]):
  166. return response.json(444, {'error param': 'uid,channel,time_stamp,size'})
  167. device_qs = Device_Info.objects.filter(UID=uid, userID=user_id).values('NickName')
  168. if not device_qs.exists():
  169. return response.json(173)
  170. # 查询是否开通云盘
  171. use_details_qs = IcloudUseDetails.objects.filter(user_id=user_id).values('id', 'use_size', 'bucket_id')
  172. if not use_details_qs.exists():
  173. return response.json(173)
  174. size = float(size) # 单位是MB
  175. use_details_id = use_details_qs[0]['id']
  176. bucket_id = use_details_qs[0]['bucket_id']
  177. use_size = float(use_details_qs[0]['use_size'])
  178. now_time = int(time.time())
  179. nickname = device_qs[0]['NickName']
  180. # 判断云盘是否还有容量
  181. all_size = IcloudService.objects.filter(Q(use_details_id=use_details_id), Q(use_status=0),
  182. Q(end_time__gt=now_time) | Q(end_time=0)).values(
  183. 'size').aggregate(total_size=Sum('size'))['total_size']
  184. all_size = all_size * 1024 if all_size else 0
  185. if use_size > all_size:
  186. logger.info('{}用户套餐总容量为:{},已使用容量为:{}'.format(uid, all_size, use_size))
  187. return response.json(910)
  188. try:
  189. new_size = round(use_size + size, 2)
  190. icloud_record_qs = IcloudStorageRecord.objects.filter(user_id=user_id, uid=uid, channel=channel,
  191. time_stamp=time_stamp,
  192. size=size, file_type=file_type)
  193. if not icloud_record_qs.exists():
  194. IcloudStorageRecord.objects.create(user_id=user_id, uid=uid, channel=channel, time_stamp=time_stamp,
  195. nickname=nickname,
  196. sec=sec, bucket_id=bucket_id, size=size,
  197. file_type=file_type)
  198. use_details_qs.update(use_size=new_size)
  199. return response.json(0)
  200. else:
  201. return response.json(174)
  202. except Exception as e:
  203. logger.info('云存转移云盘异常:{}'.format(repr(e)))
  204. return response.json(500)
  205. @staticmethod
  206. def get_upload_url(request_dict, response, user_id):
  207. """
  208. 获取s3上传地址
  209. @param request_dict: 请求参数
  210. @param user_id: 用户id
  211. @request_dict serial_number: 序列号
  212. @param response: 响应对象
  213. @return: response
  214. """
  215. logger.info('获取s3上传地址')
  216. time_stamp = request_dict.get('time_stamp', None)
  217. file_type = request_dict.get('file_type', None)
  218. uid = request_dict.get('uid', None)
  219. channel = request_dict.get('channel', None)
  220. if not all([time_stamp, uid, channel]):
  221. return response.json(444, {'error param': 'time_stamp,channel,uid'})
  222. device_qs = Device_Info.objects.filter(UID=uid, userID=user_id)
  223. if not device_qs.exists():
  224. return response.json(173)
  225. # 查询是否开通云盘
  226. use_details_qs = IcloudUseDetails.objects.filter(user_id=user_id).values('id', 'use_size', 'bucket_id')
  227. if not use_details_qs.exists():
  228. return response.json(173)
  229. use_details_id = use_details_qs[0]['id']
  230. use_size = use_details_qs[0]['use_size']
  231. bucket_id = use_details_qs[0]['bucket_id']
  232. now_time = int(time.time())
  233. # 判断云盘是否还有容量
  234. all_size = IcloudService.objects.filter(Q(use_details_id=use_details_id), Q(use_status=0),
  235. Q(end_time__gt=now_time) | Q(end_time=0)).values(
  236. 'size').aggregate(total_size=Sum('size'))['total_size']
  237. all_size = all_size * 1024 if all_size else 0
  238. excess_size = all_size - use_size
  239. if excess_size < 0:
  240. logger.info('{}用户套餐总容量为:{},已使用容量为:{}'.format(user_id, all_size, use_size))
  241. return response.json(910)
  242. bucket_qs = VodBucketModel.objects.filter(id=bucket_id).values('bucket', 'region', 'mold')
  243. if not bucket_qs.exists():
  244. return response.json(173)
  245. bucket_name = bucket_qs[0]['bucket']
  246. bucket_region = bucket_qs[0]['region']
  247. mold = bucket_qs[0]['mold']
  248. try:
  249. s3_obj = AmazonS3Util(
  250. AWS_ACCESS_KEY_ID[mold],
  251. AWS_SECRET_ACCESS_KEY[mold],
  252. bucket_region
  253. )
  254. if file_type == '0': # 图片
  255. key_name = '{user_id}/image_file/{uid}/{channel}/{time}/{time}.jpg'.format(user_id=user_id, uid=uid,
  256. channel=channel,
  257. time=time_stamp)
  258. elif file_type == '2':
  259. key_name = '{user_id}/mp4_file/{uid}/{channel}/{time}/{time}.mp4'.format(user_id=user_id, uid=uid,
  260. channel=channel,
  261. time=time_stamp)
  262. else:
  263. return response.json(444, {'error param': 'file_type'})
  264. upload_url = s3_obj.generate_put_obj_url(bucket_name, key_name)
  265. return response.json(0, {'uploadUrl': upload_url, 'excessSize': excess_size})
  266. except Exception as e:
  267. logger.info('获取s3上传地址异常:{}'.format(repr(e)))
  268. return response.json(500)