IcloudService.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. # -*- coding: utf-8 -*-
  2. """
  3. @Author : peng
  4. @Time : 2023-6-7 18:26:35
  5. @File :IcloudMeal.py
  6. """
  7. from Ansjer.config import LOGGER
  8. import time
  9. import jwt
  10. from django.db.models import Sum, Q
  11. from django.http import HttpResponse
  12. from django.views import View
  13. from Model.models import IcloudUseDetails, IcloudService, VodBucketModel, IcloudStorageRecord, Device_Info
  14. from Object.AWS.AmazonS3Util import AmazonS3Util
  15. from Object.RedisObject import RedisObject
  16. from Object.ResponseObject import ResponseObject
  17. from Object.TokenObject import TokenObject
  18. from Ansjer.config import ACCESS_KEY_ID, SECRET_ACCESS_KEY, REGION_NAME, SERVER_DOMAIN, AWS_ACCESS_KEY_ID, \
  19. AWS_SECRET_ACCESS_KEY, SERVER_DOMAIN_SSL, OAUTH_ACCESS_TOKEN_SECRET
  20. from Object.m3u8generate import PlaylistGenerator
  21. from Service.VodHlsService import SplitVodHlsObject
  22. class IcloudServiceView(View):
  23. def get(self, request, *args, **kwargs):
  24. request.encoding = 'utf-8'
  25. operation = kwargs.get('operation')
  26. return self.validation(request.GET, operation, request)
  27. def post(self, request, *args, **kwargs):
  28. request.encoding = 'utf-8'
  29. operation = kwargs.get('operation')
  30. return self.validation(request.POST, operation, request)
  31. def validation(self, request_dict, operation, request):
  32. response = ResponseObject()
  33. tko = TokenObject(request.META.get('HTTP_AUTHORIZATION'))
  34. response.lang = tko.lang
  35. user_id = tko.userID
  36. if tko.code != 0:
  37. return response.json(tko.code)
  38. if operation == 'vodUpload': # 云存上传云盘
  39. return self.vod_upload(request_dict, response, user_id)
  40. elif operation == 'getUploadUrl': # 获取s3上传地址
  41. return self.get_upload_url(request_dict, response, user_id)
  42. elif operation == 'localUpload': # 本地上传云盘
  43. return self.local_upload(request_dict, response, user_id)
  44. elif operation == 'deleteIcloudRecord': # 删除云盘记录
  45. return self.delete_icloud_record(request_dict, response, user_id)
  46. elif operation == 'getIcloudList': # 获取云盘播放列表
  47. return self.get_icloud_list(request_dict, response, user_id)
  48. elif operation == 'icloudPlay': # 云盘播放
  49. return self.icloud_play(request_dict, response, user_id)
  50. else:
  51. return response.json(404)
  52. @staticmethod
  53. def vod_upload(request_dict, response, user_id):
  54. """
  55. 云存上传云盘
  56. @param request_dict: 请求参数
  57. @param user_id: 用户id
  58. @request_dict uid: 设备uid
  59. @request_dict channel: 设备通道
  60. @request_dict start_time: 播放时间戳
  61. @param response: 响应对象
  62. @return: response
  63. """
  64. LOGGER.info('开始云存转移到云盘')
  65. uid = request_dict.get('uid', None)
  66. channel = request_dict.get('channel', None)
  67. time_stamp = request_dict.get('time_stamp', None)
  68. if not all([uid, channel, time_stamp]):
  69. return response.json(444, {'error param': 'uid,channel,start_time'})
  70. device_qs = Device_Info.objects.filter(UID=uid, userID=user_id).values('NickName')
  71. if not device_qs.exists():
  72. return response.json(173)
  73. # 查询是否开通云盘
  74. use_details_qs = IcloudUseDetails.objects.filter(user_id=user_id).values('id', 'bucket_id', 'use_size')
  75. if not use_details_qs.exists():
  76. return response.json(173)
  77. use_details_id = use_details_qs[0]['id']
  78. target_bucket_id = use_details_qs[0]['bucket_id']
  79. use_size = float(use_details_qs[0]['use_size'])
  80. now_time = int(time.time())
  81. nickname = device_qs[0]['NickName']
  82. # 判断云盘是否还有容量
  83. all_size = IcloudService.objects.filter(Q(use_details_id=use_details_id), Q(use_status=0),
  84. Q(end_time__gt=now_time) | Q(end_time=0)).values(
  85. 'size').aggregate(total_size=Sum('size'))['total_size']
  86. all_size = all_size * 1024 if all_size else 0
  87. if use_size > all_size:
  88. LOGGER.info('{}用户套餐总容量为:{},已使用容量为:{}'.format(uid, all_size, use_size))
  89. return response.json(910)
  90. split_vod_hls_obj = SplitVodHlsObject()
  91. vod_hls = split_vod_hls_obj.get_vod_hls_data(uid=uid, channel=channel, start_time=time_stamp).values(
  92. 'bucket_id', 'fg', 'sec')
  93. if not vod_hls.exists():
  94. LOGGER.info('{}用户查无此云存:{}'.format(uid, time_stamp))
  95. return response.json(173)
  96. source_bucket_id = vod_hls[0]['bucket_id']
  97. fg = int(vod_hls[0]['fg'])
  98. sec = vod_hls[0]['sec']
  99. target_bucket_qs = VodBucketModel.objects.filter(id=target_bucket_id).values('bucket')
  100. if not target_bucket_qs.exists():
  101. return response.json(173)
  102. target_bucket_name = target_bucket_qs[0]['bucket']
  103. source_bucket_qs = VodBucketModel.objects.filter(id=source_bucket_id).values('bucket', 'region', 'mold')
  104. if not source_bucket_qs.exists():
  105. return response.json(173)
  106. bucket_region = source_bucket_qs[0]['region']
  107. source_bucket_name = source_bucket_qs[0]['bucket']
  108. mold = source_bucket_qs[0]["mold"]
  109. ts_list = []
  110. ts_size = 0
  111. try:
  112. s3_obj = AmazonS3Util(
  113. AWS_ACCESS_KEY_ID[mold],
  114. AWS_SECRET_ACCESS_KEY[mold],
  115. bucket_region
  116. )
  117. # 获取视频封面
  118. thumbs_png = '{uid}/vod{channel}/{time}/Thumb.jpeg'.format(uid=uid, channel=channel, time=time_stamp)
  119. thumbs_png_size = s3_obj.get_object_size(source_bucket_name, thumbs_png)
  120. if thumbs_png_size:
  121. ts_size += thumbs_png_size
  122. ts_list.append(thumbs_png)
  123. # 获取s3对象,并计算总字节
  124. for i in range(15):
  125. shift = (i + 1) * 4
  126. duration = (fg >> shift) & 0xf
  127. if duration > 0:
  128. ts_file = '{uid}/vod{channel}/{time}/ts{i}.ts'.format(uid=uid, channel=channel, time=time_stamp,
  129. i=i)
  130. ts_list.append(ts_file)
  131. ts_size += s3_obj.get_object_size(source_bucket_name, ts_file) # 获取存储对象字节,单位B
  132. ts_size = round(ts_size / 1024 / 1024, 2) # 字节转换为MB单位
  133. temp_size = ts_size + use_size
  134. if temp_size > all_size:
  135. LOGGER.info('{}用户无空间上传,套餐容量为:{},使用容量为:{}'.format(uid, all_size, temp_size))
  136. return response.json(910)
  137. time_stamp = int(time_stamp) * 1000 # 转换单位为毫秒
  138. icloud_record_qs = IcloudStorageRecord.objects.filter(user_id=user_id, uid=uid, channel=channel,
  139. time_stamp=time_stamp,
  140. size=ts_size, file_type=1)
  141. if not icloud_record_qs.exists(): # 转移云盘,并记录上传记录,更新使用容量
  142. for source_key in ts_list:
  143. ts_name = source_key.split('/')[-1]
  144. target_key = '{user_id}/ts_file/{uid}/channel{channel}/{time}/{ts_name}'.format(user_id=user_id,
  145. uid=uid,
  146. channel=channel,
  147. time=time_stamp,
  148. ts_name=ts_name)
  149. s3_obj.copy_single_obj(source_bucket_name, source_key, target_bucket_name, target_key)
  150. IcloudStorageRecord.objects.create(user_id=user_id, uid=uid, channel=channel, time_stamp=time_stamp,
  151. nickname=nickname,
  152. sec=sec, bucket_id=target_bucket_id, fg=fg, size=ts_size,
  153. file_type=1)
  154. use_details_qs.update(use_size=temp_size)
  155. return response.json(0)
  156. else:
  157. return response.json(174)
  158. except Exception as e:
  159. LOGGER.info('云存转移云盘异常:{}'.format(repr(e)))
  160. return response.json(500)
  161. @staticmethod
  162. def local_upload(request_dict, response, user_id):
  163. """
  164. 本地上传云盘
  165. @param request_dict: 请求参数
  166. @param user_id: 用户id
  167. @request_dict uid: 设备uid
  168. @request_dict channel: 设备通道
  169. @request_dict time_stamp: 时间戳
  170. @request_dict size: 文件大小
  171. @request_dict file_type: 文件类型
  172. @request_dict sec: 时长
  173. @param response: 响应对象
  174. @return: response
  175. """
  176. LOGGER.info('开始本地转移到云盘')
  177. uid = request_dict.get('uid', None)
  178. channel = request_dict.get('channel', None)
  179. time_stamp = request_dict.get('time_stamp', None)
  180. size = request_dict.get('size', None)
  181. file_type = request_dict.get('file_type', None)
  182. sec = request_dict.get('sec', 0)
  183. if not all([uid, channel, time_stamp, size]):
  184. return response.json(444, {'error param': 'uid,channel,time_stamp,size'})
  185. device_qs = Device_Info.objects.filter(UID=uid, userID=user_id).values('NickName')
  186. if not device_qs.exists():
  187. return response.json(173)
  188. # 查询是否开通云盘
  189. use_details_qs = IcloudUseDetails.objects.filter(user_id=user_id).values('id', 'use_size', 'bucket_id')
  190. if not use_details_qs.exists():
  191. return response.json(173)
  192. size = float(size) # 单位是MB
  193. use_details_id = use_details_qs[0]['id']
  194. bucket_id = use_details_qs[0]['bucket_id']
  195. use_size = float(use_details_qs[0]['use_size'])
  196. now_time = int(time.time())
  197. nickname = device_qs[0]['NickName']
  198. # 判断云盘是否还有容量
  199. all_size = IcloudService.objects.filter(Q(use_details_id=use_details_id), Q(use_status=0),
  200. Q(end_time__gt=now_time) | Q(end_time=0)).values(
  201. 'size').aggregate(total_size=Sum('size'))['total_size']
  202. all_size = all_size * 1024 if all_size else 0
  203. if use_size > all_size:
  204. LOGGER.info('{}用户套餐总容量为:{},已使用容量为:{}'.format(uid, all_size, use_size))
  205. return response.json(910)
  206. try:
  207. new_size = round(use_size + size, 2)
  208. icloud_record_qs = IcloudStorageRecord.objects.filter(user_id=user_id, uid=uid, channel=channel,
  209. time_stamp=time_stamp,
  210. size=size, file_type=file_type)
  211. if not icloud_record_qs.exists():
  212. IcloudStorageRecord.objects.create(user_id=user_id, uid=uid, channel=channel, time_stamp=time_stamp,
  213. nickname=nickname,
  214. sec=sec, bucket_id=bucket_id, size=size,
  215. file_type=file_type)
  216. use_details_qs.update(use_size=new_size)
  217. return response.json(0)
  218. else:
  219. return response.json(174)
  220. except Exception as e:
  221. LOGGER.info('本地转移云盘异常:{}'.format(repr(e)))
  222. return response.json(500)
  223. @staticmethod
  224. def get_upload_url(request_dict, response, user_id):
  225. """
  226. 获取s3上传地址
  227. @param request_dict: 请求参数
  228. @param user_id: 用户id
  229. @request_dict time_stamp: 时间戳
  230. @request_dict file_type: 文件类型
  231. @request_dict uid: 设备uid
  232. @request_dict channel: 设备通道
  233. @param response: 响应对象
  234. @return: response
  235. """
  236. LOGGER.info('获取s3上传地址')
  237. time_stamp = request_dict.get('time_stamp', None)
  238. file_type = request_dict.get('file_type', None)
  239. uid = request_dict.get('uid', None)
  240. channel = request_dict.get('channel', None)
  241. if not all([time_stamp, uid, channel]):
  242. return response.json(444, {'error param': 'time_stamp,channel,uid'})
  243. device_qs = Device_Info.objects.filter(UID=uid, userID=user_id)
  244. if not device_qs.exists():
  245. return response.json(173)
  246. # 查询是否开通云盘
  247. use_details_qs = IcloudUseDetails.objects.filter(user_id=user_id).values('id', 'use_size', 'bucket_id')
  248. if not use_details_qs.exists():
  249. return response.json(173)
  250. use_details_id = use_details_qs[0]['id']
  251. use_size = use_details_qs[0]['use_size']
  252. bucket_id = use_details_qs[0]['bucket_id']
  253. now_time = int(time.time())
  254. # 判断云盘是否还有容量
  255. all_size = IcloudService.objects.filter(Q(use_details_id=use_details_id), Q(use_status=0),
  256. Q(end_time__gt=now_time) | Q(end_time=0)).values(
  257. 'size').aggregate(total_size=Sum('size'))['total_size']
  258. all_size = all_size * 1024 if all_size else 0
  259. excess_size = all_size - use_size
  260. if excess_size < 0:
  261. LOGGER.info('{}用户套餐总容量为:{},已使用容量为:{}'.format(user_id, all_size, use_size))
  262. return response.json(910)
  263. bucket_qs = VodBucketModel.objects.filter(id=bucket_id).values('bucket', 'region', 'mold')
  264. if not bucket_qs.exists():
  265. return response.json(173)
  266. bucket_name = bucket_qs[0]['bucket']
  267. bucket_region = bucket_qs[0]['region']
  268. mold = bucket_qs[0]['mold']
  269. try:
  270. s3_obj = AmazonS3Util(
  271. AWS_ACCESS_KEY_ID[mold],
  272. AWS_SECRET_ACCESS_KEY[mold],
  273. bucket_region
  274. )
  275. if file_type == '0': # 图片
  276. key_name = '{user_id}/image_file/{uid}/channel{channel}/{time}/{time}.jpeg'.format(user_id=user_id,
  277. uid=uid,
  278. channel=channel,
  279. time=time_stamp)
  280. elif file_type == '2':
  281. key_name = '{user_id}/mp4_file/{uid}/channel{channel}/{time}/{time}.mp4'.format(user_id=user_id,
  282. uid=uid,
  283. channel=channel,
  284. time=time_stamp)
  285. else:
  286. return response.json(444, {'error param': 'file_type'})
  287. upload_url = s3_obj.generate_put_obj_url(bucket_name, key_name)
  288. return response.json(0, {'uploadUrl': upload_url, 'excessSize': excess_size})
  289. except Exception as e:
  290. LOGGER.info('获取s3上传地址异常:{}'.format(repr(e)))
  291. return response.json(500)
  292. @staticmethod
  293. def delete_icloud_record(request_dict, response, user_id):
  294. """
  295. 删除云盘记录
  296. @param request_dict: 请求参数
  297. @param user_id: 用户id
  298. @request_dict time_stamp: 时间戳
  299. @request_dict uid: 设备uid
  300. @request_dict channel: 设备通道
  301. @request_dict file_type: 文件类型
  302. @param response: 响应对象
  303. @return: response
  304. """
  305. LOGGER.info('删除云盘记录')
  306. time_stamp = request_dict.get('time_stamp', None)
  307. file_type = request_dict.get('file_type', None)
  308. uid = request_dict.get('uid', None)
  309. channel = request_dict.get('channel', None)
  310. if not all([time_stamp, uid, channel]):
  311. return response.json(444, {'error param': 'time_stamp,channel,uid'})
  312. # 查询是否开通云盘
  313. use_details_qs = IcloudUseDetails.objects.filter(user_id=user_id).values('use_size', 'bucket_id')
  314. if not use_details_qs.exists():
  315. return response.json(173)
  316. use_size = float(use_details_qs[0]['use_size'])
  317. bucket_id = use_details_qs[0]['bucket_id']
  318. icloud_record_qs = IcloudStorageRecord.objects.filter(user_id=user_id, uid=uid, channel=channel,
  319. time_stamp=time_stamp,
  320. bucket_id=bucket_id, file_type=file_type)
  321. if not icloud_record_qs.exists():
  322. return response.json(173)
  323. record_qs = icloud_record_qs.values('size')
  324. size = float(record_qs[0]['size'])
  325. bucket_qs = VodBucketModel.objects.filter(id=bucket_id).values('bucket', 'region', 'mold')
  326. if not bucket_qs.exists():
  327. return response.json(173)
  328. bucket_name = bucket_qs[0]['bucket']
  329. bucket_region = bucket_qs[0]['region']
  330. mold = bucket_qs[0]['mold']
  331. try:
  332. s3_obj = AmazonS3Util(
  333. AWS_ACCESS_KEY_ID[mold],
  334. AWS_SECRET_ACCESS_KEY[mold],
  335. bucket_region
  336. )
  337. new_size = round(use_size - size, 2)
  338. new_size = new_size if new_size > 0 else 0
  339. if file_type == '0': # 图片
  340. key_name = '{user_id}/image_file/{uid}/vod{channel}/{time}'.format(user_id=user_id, uid=uid,
  341. channel=channel,
  342. time=time_stamp)
  343. object_list = s3_obj.get_object_list(bucket_name, key_name)
  344. elif file_type == '1': # ts文件
  345. key_name = '{user_id}/ts_file/{uid}/vod{channel}/{time}'.format(user_id=user_id, uid=uid,
  346. channel=channel,
  347. time=time_stamp)
  348. object_list = s3_obj.get_object_list(bucket_name, key_name)
  349. elif file_type == '2': # mp4文件
  350. key_name = '{user_id}/mp4_file/{uid}/vod{channel}/{time}'.format(user_id=user_id, uid=uid,
  351. channel=channel,
  352. time=time_stamp)
  353. object_list = s3_obj.get_object_list(bucket_name, key_name)
  354. else:
  355. return response.json(444, {'error param': 'file_type'})
  356. for item in object_list:
  357. s3_obj.delete_obj(bucket_name, item['Key'])
  358. icloud_record_qs.delete()
  359. use_details_qs.update(use_size=new_size)
  360. return response.json(0)
  361. except Exception as e:
  362. LOGGER.info('删除云盘记录异常:{}'.format(repr(e)))
  363. return response.json(500)
  364. @staticmethod
  365. def get_icloud_list(request_dict, response, user_id):
  366. """
  367. 获取云盘播放列表
  368. @param request_dict: 请求参数
  369. @param user_id: 用户id
  370. @request_dict time_stamp: 时间戳
  371. @request_dict uid: 设备uid
  372. @request_dict channel: 设备通道
  373. @param response: 响应对象
  374. @return: response
  375. """
  376. LOGGER.info('删除云盘记录')
  377. start_time = request_dict.get('start_time', None)
  378. end_time = request_dict.get('end_time', None)
  379. nick_name = request_dict.get('nick_name', None)
  380. file_type = request_dict.get('file_type', None)
  381. page = request_dict.get('page', None)
  382. line = request_dict.get('line', None)
  383. if not all([page, line]):
  384. return response.json(444, {'error param': 'page, line'})
  385. page = int(page)
  386. line = int(line)
  387. now_time = int(time.time())
  388. icloud_list = []
  389. use_details_qs = IcloudUseDetails.objects.filter(user_id=user_id).values('id')
  390. if not use_details_qs.exists():
  391. return response.json(173)
  392. use_details_id = use_details_qs[0]['id']
  393. all_size = IcloudService.objects.filter(Q(use_details_id=use_details_id), Q(use_status=0),
  394. Q(end_time__gt=now_time) | Q(end_time=0)).values(
  395. 'size').aggregate(total_size=Sum('size'))['total_size']
  396. all_size = all_size * 1024 if all_size else 0 # 转换单位为MB
  397. icloud_record_qs = IcloudStorageRecord.objects.filter(user_id=user_id)
  398. if start_time and end_time: # 按时间段查询
  399. icloud_record_qs = icloud_record_qs.filter(time_stamp__gte=start_time, time_stamp__lt=end_time)
  400. if nick_name: # 按设备昵称查询
  401. icloud_record_qs = icloud_record_qs.filter(nickname=nick_name)
  402. if file_type: # 按文件类型查询
  403. icloud_record_qs = icloud_record_qs.filter(file_type=file_type)
  404. icloud_record_qs = icloud_record_qs.values('bucket_id', 'sec', 'fg', 'nickname', 'uid', 'channel', 'size', 'id',
  405. 'time_stamp', 'file_type').order_by('-time_stamp')[
  406. (page - 1) * line:page * line]
  407. if not icloud_record_qs.exists():
  408. return response.json(0, icloud_list)
  409. bucket_id = icloud_record_qs[0]['bucket_id']
  410. bucket_qs = VodBucketModel.objects.filter(id=bucket_id).values('bucket', 'region', 'mold')
  411. if not bucket_qs.exists():
  412. return response.json(173)
  413. bucket_name = bucket_qs[0]['bucket']
  414. bucket_region = bucket_qs[0]['region']
  415. mold = bucket_qs[0]['mold']
  416. total_size = 0
  417. try:
  418. s3_obj = AmazonS3Util(
  419. AWS_ACCESS_KEY_ID[mold],
  420. AWS_SECRET_ACCESS_KEY[mold],
  421. bucket_region
  422. )
  423. for item in icloud_record_qs:
  424. uid = item['uid']
  425. channel = item['channel']
  426. time_stamp = item['time_stamp']
  427. file_type = item['file_type']
  428. total_size += float(item['size'])
  429. uid_token = TokenObject().encryption(data={'uid': uid})
  430. res_data = {
  431. 'is_show': 1 if total_size < all_size else 0, # 只展示剩余容量的数据,超过的部分不展示
  432. 'time_stamp': time_stamp,
  433. 'icloud_id': item['id'],
  434. 'file_type': file_type,
  435. 'nick_name': item['nickname']
  436. }
  437. if file_type == 0: # 图片,只返回图片地址
  438. thumbs_png = '{user_id}/image_file/{uid}/channel{channel}/{time}/{time}.jpeg'.format(
  439. user_id=user_id,
  440. uid=uid,
  441. channel=channel,
  442. time=time_stamp)
  443. response_url = s3_obj.generate_file_obj_url(bucket_name, thumbs_png)
  444. res_data['thumb'] = response_url
  445. icloud_list.append(res_data)
  446. elif file_type == 1: # ts文件,返回播放地址
  447. thumbs_png = '{user_id}/image_file/{uid}/channel{channel}/{time}/{time}.jpeg'.format(
  448. user_id=user_id,
  449. uid=uid,
  450. channel=channel,
  451. time=time_stamp)
  452. response_url = s3_obj.generate_file_obj_url(bucket_name, thumbs_png)
  453. ts_num = int(item['fg']) & 0xf
  454. res_data['thumb'] = response_url
  455. icloud_url = '{server_domain}icloud/service/icloudPlay?' \
  456. 'uid={uid}&channel={channel}&time_stamp={time_stamp}&file_type=1&sign=tktktktk'. \
  457. format(server_domain=SERVER_DOMAIN_SSL, uid=uid_token, channel=channel, time_stamp=time_stamp)
  458. res_data['ts_num'] = ts_num
  459. res_data['icloud_url'] = icloud_url
  460. res_data['sec'] = item['sec']
  461. icloud_list.append(res_data)
  462. elif file_type == 2: # mp4文件,返回播放地址
  463. mp4_file = '{user_id}/mp4_file/{uid}/channel{channel}/{time}/{time}.mp4'.format(
  464. user_id=user_id,
  465. uid=uid,
  466. channel=channel,
  467. time=time_stamp)
  468. response_url = s3_obj.generate_file_obj_url(bucket_name, mp4_file)
  469. res_data['icloud_url'] = response_url
  470. res_data['sec'] = item['sec']
  471. icloud_list.append(res_data)
  472. return response.json(0, icloud_list)
  473. except Exception as e:
  474. LOGGER.info('获取云盘播放列表异常:{}'.format(repr(e)))
  475. return response.json(500)
  476. @staticmethod
  477. def icloud_play(request_dict, response, user_id):
  478. """
  479. 云盘播放
  480. @param request_dict: 请求参数
  481. @param user_id: 用户id
  482. @request_dict time_stamp: 时间戳
  483. @request_dict uid: 设备uid
  484. @request_dict channel: 设备通道
  485. @param response: 响应对象
  486. @return: response
  487. """
  488. LOGGER.info('播放云盘记录')
  489. time_stamp = request_dict.get('time_stamp', None)
  490. uid_token = request_dict.get('uid', None)
  491. channel = request_dict.get('channel', None)
  492. file_type = request_dict.get('file_type', None)
  493. if not all([time_stamp, uid_token, channel, file_type]):
  494. return response.json(444, {'error param': 'time_stamp, uid_token, channel, file_type'})
  495. if file_type != '1':
  496. return response.json(444, {'error param': 'file_type'})
  497. uid = jwt.decode(uid_token, OAUTH_ACCESS_TOKEN_SECRET, algorithms='HS256').get('uid', '')
  498. icloud_record_qs = IcloudStorageRecord.objects.filter(user_id=user_id, uid=uid, channel=channel,
  499. file_type=file_type,
  500. time_stamp=time_stamp).values('bucket_id', 'fg')
  501. if not icloud_record_qs.exists():
  502. return response.json(173)
  503. bucket_id = icloud_record_qs[0]['bucket_id']
  504. fg = int(icloud_record_qs[0]['fg'])
  505. bucket_qs = VodBucketModel.objects.filter(id=bucket_id).values('bucket', 'region', 'mold')
  506. if not bucket_qs.exists():
  507. return response.json(173)
  508. bucket_name = bucket_qs[0]['bucket']
  509. bucket_region = bucket_qs[0]['region']
  510. mold = bucket_qs[0]['mold']
  511. try:
  512. s3_obj = AmazonS3Util(
  513. AWS_ACCESS_KEY_ID[mold],
  514. AWS_SECRET_ACCESS_KEY[mold],
  515. bucket_region
  516. )
  517. playlist_entries = []
  518. for i in range(15):
  519. shift = (i + 1) * 4
  520. duration = (fg >> shift) & 0xf
  521. if duration > 0:
  522. ts_file = '{user_id}/ts_file/{uid}/channel{channel}/{time_stamp}/ts{i}.ts'.format(
  523. user_id=user_id, uid=uid, channel=channel, time_stamp=time_stamp, i=i)
  524. response_url = s3_obj.generate_file_obj_url(bucket_name, ts_file)
  525. playlist_entries.append({
  526. 'name': response_url,
  527. 'duration': duration,
  528. })
  529. playlist = PlaylistGenerator(playlist_entries).generate()
  530. response = HttpResponse(playlist)
  531. response['Content-Type'] = 'application/octet-stream'
  532. response['Content-Disposition'] = 'attachment;filename="play.m3u8"'
  533. return response
  534. except Exception as e:
  535. LOGGER.info('云盘播放异常:{}'.format(repr(e)))
  536. return response.json(500)