#!/usr/bin/env python # -*- coding:utf-8 -*- # project: 3月 # author: liuyu # date: 2020/3/6 from rest_framework.views import APIView from api.utils.response import BaseResponse from rest_framework.response import Response from fir_ser import settings from api.utils.TokenManager import DownloadToken from api.utils.app.randomstrings import make_random_uuid from api.utils.app.apputils import make_resigned from api.utils.app.supersignutils import make_udid_mobileconfig,get_post_udid_url from api.utils.storage.storage import Storage from api.utils.storage.caches import get_app_instance_by_cache,get_download_url_by_cache,set_app_download_by_cache,del_cache_response_by_short import os from rest_framework_extensions.cache.decorators import cache_response from api.utils.serializer import AppsShortSerializer from api.models import Apps,AppReleaseInfo from django.http import FileResponse class DownloadView(APIView): ''' 文件下载接口,适用于本地存储和所有plist文件下载 ''' # authentication_classes = [ExpiringTokenAuthentication, ] # parser_classes = (MultiPartParser,) def get(self,request,filename): res = BaseResponse() downtoken = request.query_params.get("token", None) ftype = request.query_params.get("ftype",None) if not downtoken: res.code=1004 res.msg="缺失token" return Response(res.dict) dtoken = DownloadToken() if dtoken.verify_token(downtoken,filename): if not ftype: file_path = os.path.join(settings.MEDIA_ROOT, filename) try: response = FileResponse(open(file_path, 'rb')) except Exception as e: print(e) response = FileResponse() response['content_type'] = "application/octet-stream" response['Content-Disposition'] = 'attachment; filename=' + filename return response else: if ftype == 'plist': release_obj = AppReleaseInfo.objects.filter(release_id=filename.split('.')[0]).first() if release_obj: storage = Storage(release_obj.app_id.user_id) bundle_id = release_obj.app_id.bundle_id app_version = release_obj.app_version name = release_obj.app_id.name ios_plist_bytes = make_resigned(storage.get_download_url(filename),storage.get_download_url(release_obj.icon_url),bundle_id,app_version,name) response = FileResponse(ios_plist_bytes) response['Content-Type'] = "application/x-plist" response['Content-Disposition'] = 'attachment; filename=' + make_random_uuid() return response elif ftype == 'mobileconifg': release_obj = AppReleaseInfo.objects.filter(release_id=filename.split('.')[0]).first() if release_obj: bundle_id = release_obj.app_id.bundle_id udid_url = get_post_udid_url(request,release_obj.app_id.short) ios_udid_mobileconfig = make_udid_mobileconfig(udid_url, bundle_id) response = FileResponse(ios_udid_mobileconfig) response['Content-Type'] = "application/x-apple-aspen-config" response['Content-Disposition'] = 'attachment; filename=' + make_random_uuid() +'.mobileconfig' return response res.code=1004 res.msg="token校验失败" return Response(res.dict) class ShortDownloadView(APIView): ''' 根据下载短链接,获取应用信息 ''' @cache_response(timeout=600-60, cache="default",key_func='calculate_cache_key',cache_errors=False) def get(self,request,short): res = BaseResponse() release_id = request.query_params.get("release_id", None) udid = request.query_params.get("udid", None) app_obj = Apps.objects.filter(short=short).first() if udid: del_cache_response_by_short(short,app_obj.app_id,udid=udid) if not app_obj: res.code=1003 res.msg="该应用不存在" return Response(res.dict) if not app_obj.isshow: res.code=1004 res.msg="您没有权限访问该应用" return Response(res.dict) app_serializer = AppsShortSerializer(app_obj,context={"key":"ShortDownloadView","release_id":release_id,"storage":Storage(app_obj.user_id)}) res.data = app_serializer.data res.udid = udid return Response(res.dict) #key的设置 def calculate_cache_key(self, view_instance, view_method, request, args, kwargs): release_id = request.query_params.get("release_id", '') udid = request.query_params.get("udid", None) time = request.query_params.get("time", None) if udid and time: udid=time if not udid: udid="" return "_".join([settings.CACHE_KEY_TEMPLATE.get("download_short_key"), kwargs.get("short", ''),release_id,udid]) class InstallView(APIView): ''' 安装操作,前端通过token 认证,认证成功之后,返回 下载连接,并且 让下载次数加一 ''' def get(self,request,app_id): res = BaseResponse() downtoken = request.query_params.get("token", None) short = request.query_params.get("short",None) release_id = request.query_params.get("release_id",None) isdownload = request.query_params.get("isdownload",None) password = request.query_params.get("password",None) udid = request.query_params.get("udid",None) if not downtoken or not short or not release_id: res.code=1004 res.msg="参数丢失" return Response(res.dict) dtoken = DownloadToken() if dtoken.verify_token(downtoken,release_id): app_obj = get_app_instance_by_cache(app_id,password,900,udid) if app_obj: if app_obj.get("type") == 0: apptype = '.apk' download_url = get_download_url_by_cache(app_obj,release_id + apptype,600) else: apptype = '.ipa' if isdownload : download_url = get_download_url_by_cache(app_obj,release_id + apptype, 600,udid=udid) else: download_url = get_download_url_by_cache(app_obj,release_id + apptype,600,isdownload,udid=udid) res.data={"download_url":download_url} if download_url!= "": set_app_download_by_cache(app_id) return Response(res.dict) else: res.code = 1004 res.msg = "token校验失败" return Response(res.dict) res.code = 1006 res.msg = "该应用不存在" return Response(res.dict)