优化下载流程

super_signature
nineven 5 years ago
parent f72be06618
commit 5f7873c29f
  1. 28
      fir_ser/api/migrations/0018_auto_20200407_1134.py
  2. 18
      fir_ser/api/migrations/0019_auto_20200407_1135.py
  3. 21
      fir_ser/api/migrations/0020_auto_20200407_1157.py
  4. 9
      fir_ser/api/models.py
  5. 2
      fir_ser/api/utils/app/apputils.py
  6. 4
      fir_ser/api/utils/storage/storage.py
  7. 16
      fir_ser/api/views/apps.py
  8. 51
      fir_ser/api/views/download.py
  9. 2
      fir_ser/api/views/uploads.py

@ -0,0 +1,28 @@
# Generated by Django 3.0.3 on 2020-04-07 03:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0017_auto_20200331_1543'),
]
operations = [
migrations.AlterField(
model_name='appreleaseinfo',
name='release_id',
field=models.CharField(db_index=True, max_length=64, unique=True, verbose_name='release 版本id'),
),
migrations.AlterField(
model_name='apps',
name='app_id',
field=models.CharField(db_index=True, max_length=64, unique=True),
),
migrations.AlterField(
model_name='apps',
name='short',
field=models.CharField(db_index=True, max_length=16, unique=True, verbose_name='短链接'),
),
]

@ -0,0 +1,18 @@
# Generated by Django 3.0.3 on 2020-04-07 03:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0018_auto_20200407_1134'),
]
operations = [
migrations.AlterField(
model_name='userinfo',
name='uid',
field=models.CharField(db_index=True, max_length=64, unique=True),
),
]

@ -0,0 +1,21 @@
# Generated by Django 3.0.3 on 2020-04-07 03:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0019_auto_20200407_1135'),
]
operations = [
migrations.AddIndex(
model_name='apps',
index=models.Index(fields=['app_id'], name='api_apps_app_id_4c0254_idx'),
),
migrations.AddIndex(
model_name='apps',
index=models.Index(fields=['id', 'user_id', 'type'], name='api_apps_id_226a6b_idx'),
),
]

@ -19,7 +19,7 @@ class UserInfo(AbstractUser):
blank=True,
null=True
)
uid = models.CharField(max_length=64, unique=True) # user_id,唯一标识
uid = models.CharField(max_length=64, unique=True,db_index=True) # user_id,唯一标识
mobile = models.BigIntegerField(verbose_name="手机", unique=True, help_text="用于手机验证码登录", null=True)
qq = models.BigIntegerField(verbose_name="QQ", blank=True, null=True, db_index=True)
is_active = models.BooleanField(default=True, verbose_name="账户状态,默认启用")
@ -92,12 +92,12 @@ class VerifyName(models.Model):
######################################## APP表 ########################################
class Apps(models.Model):
app_id = models.CharField(max_length=64, unique=True) # ,唯一标识
app_id = models.CharField(max_length=64, unique=True,db_index=True) # ,唯一标识
user_id = models.ForeignKey(to="UserInfo",verbose_name="用户ID",on_delete=models.CASCADE)
type_choices = ((0, 'android'),(1, 'ios'))
type = models.SmallIntegerField(choices=type_choices, default=0, verbose_name="类型")
name = models.CharField(max_length=32,blank=True, null=True,verbose_name="应用名称")
short = models.CharField(max_length=16,unique=True,verbose_name="短链接")
short = models.CharField(max_length=16,unique=True,verbose_name="短链接",db_index=True)
bundle_id = models.CharField(max_length=64,blank=True,verbose_name="bundle id")
has_combo = models.OneToOneField(to="Apps", related_name='combo_app_info',
verbose_name="关联应用",on_delete=models.SET_NULL,null=True,blank=True)
@ -109,6 +109,7 @@ class Apps(models.Model):
class Meta:
verbose_name = '应用信息'
verbose_name_plural = "应用信息"
indexes = [models.Index(fields=['app_id']),models.Index(fields=['id','user_id','type'])]
def __str__(self):
return "%s %s" % (self.name,self.get_type_display())
@ -116,7 +117,7 @@ class Apps(models.Model):
class AppReleaseInfo(models.Model):
is_master = models.BooleanField(verbose_name="是否master版本",default=True)
release_id = models.CharField(max_length=64, unique=True,verbose_name="release 版本id")
release_id = models.CharField(max_length=64, unique=True,verbose_name="release 版本id",db_index=True)
app_id = models.ForeignKey(to="Apps",on_delete=models.CASCADE,verbose_name="属于哪个APP")
build_version = models.CharField(max_length=16,verbose_name="build版本",blank=True)
app_version = models.CharField(max_length=16,verbose_name="app版本",blank=True)

@ -129,7 +129,7 @@ def SaveAppInfos(app_file_name,user_obj,appinfo,bundle_id,app_img,short,size):
return
else:
try:
del_cache_response_by_short(appmobj.short)
del_cache_response_by_short(appmobj.short,appmobj.app_id)
appmobj.short = short
appmobj.name = appinfo["labelname"]
appmobj.save()

@ -105,7 +105,7 @@ class Storage(object):
def del_cache_response_by_short(short):
def del_cache_response_by_short(short,app_id):
id = "download"
rtn = '_'.join([
id,
@ -113,3 +113,5 @@ def del_cache_response_by_short(short):
short
])
cache.delete(rtn)
app_obj_key = "%s_%s" % ('app_instance', app_id)
cache.delete(app_obj_key)

@ -116,11 +116,11 @@ class AppInfoView(APIView):
has_combo = apps_obj.has_combo
if has_combo:
del_cache_response_by_short(apps_obj.has_combo.short)
del_cache_response_by_short(apps_obj.has_combo.short,apps_obj.has_combo.app_id)
apps_obj.has_combo.has_combo = None
apps_obj.delete()
del_cache_response_by_short(apps_obj.short)
del_cache_response_by_short(apps_obj.short,apps_obj.app_id)
return Response(res.dict)
@ -148,8 +148,8 @@ class AppInfoView(APIView):
has_combo.update(**{"has_combo": apps_obj.first()})
else:
pass
del_cache_response_by_short(apps_obj.first().short)
del_cache_response_by_short(has_combo.first().short)
del_cache_response_by_short(apps_obj.first().short,apps_obj.first().app_id)
del_cache_response_by_short(has_combo.first().short,has_combo.first().app_id)
except Exception as e:
res.code = 1004
@ -158,7 +158,7 @@ class AppInfoView(APIView):
try:
apps_obj = Apps.objects.filter(user_id=request.user, app_id=app_id).first()
apps_obj.description = data.get("description", apps_obj.description)
del_cache_response_by_short(apps_obj.short)
del_cache_response_by_short(apps_obj.short,apps_obj.app_id)
apps_obj.short = data.get("short", apps_obj.short)
apps_obj.name = data.get("name", apps_obj.name)
apps_obj.save()
@ -211,7 +211,7 @@ class AppInfoView(APIView):
release_obj.icon_url = release_obj.icon_url.replace(old_file_name.split(".")[0],
random_file_name)
release_obj.save()
del_cache_response_by_short(apps_obj.short)
del_cache_response_by_short(apps_obj.short,apps_obj.app_id)
storage = Storage(request.user)
storage.delete_file(old_file_name)
@ -270,7 +270,7 @@ class AppReleaseinfoView(APIView):
apps_obj.delete()
else:
pass
del_cache_response_by_short(apps_obj.short)
del_cache_response_by_short(apps_obj.short,apps_obj.app_id)
return Response(res.dict)
@ -306,7 +306,7 @@ class AppReleaseinfoView(APIView):
res.msg = "更新失败"
return Response(res.dict)
del_cache_response_by_short(apps_obj.short)
del_cache_response_by_short(apps_obj.short,apps_obj.app_id)
app_serializer = AppsSerializer(apps_obj)
res.data["currentapp"] = app_serializer.data

@ -11,11 +11,13 @@ 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.storage.storage import Storage,LocalStorage
import os
import os,time
from django.core.cache import cache
from rest_framework_extensions.cache.decorators import cache_response
from api.utils.serializer import AppsSerializer
from api.models import Apps,AppReleaseInfo
from api.models import Apps,AppReleaseInfo,UserInfo
from django.db.models import F
from django.http import FileResponse
class DownloadView(APIView):
'''
@ -115,28 +117,24 @@ class InstallView(APIView):
dtoken = DownloadToken()
if dtoken.verify_token(downtoken,release_id):
app_obj = Apps.objects.filter(app_id=app_id,short=short).first()
# app_obj = Apps.objects.filter(app_id=app_id).values("pk",'user_id','type','short').first()
app_obj = self.get_app_instance_by_cache(app_id,900)
if app_obj:
app_obj.count_hits = app_obj.count_hits+1
app_obj.save()
app_obj.user_id.all_download_times = app_obj.user_id.all_download_times+1
app_obj.user_id.save()
Apps.objects.filter(app_id=app_id).update(count_hits=F('count_hits') + 1)
UserInfo.objects.filter(pk=app_obj.get("user_id")).update(all_download_times=F('all_download_times') + 1)
release_obj = AppReleaseInfo.objects.filter(app_id=app_obj,release_id=release_id).first()
if release_obj:
storage = Storage(app_obj.user_id)
if app_obj.type == 0:
# release_obj = AppReleaseInfo.objects.filter(app_id=app_obj.get('pk')).values("release_id")
# if release_obj:
if app_obj.get("type") == 0:
apptype = '.apk'
download_url = storage.get_download_url(release_obj.release_id + apptype,600)
download_url = self.get_download_url_by_cache(app_obj,release_id + apptype,600)
else:
apptype = '.ipa'
if isdownload :
download_url = storage.get_download_url(release_obj.release_id + apptype, 600)
download_url = self.get_download_url_by_cache(app_obj,release_id + apptype, 600)
else:
local_storage = LocalStorage('localhost',False)
# print(local_storage.get_download_url(release_obj.release_id + apptype,600,'plist'))
download_url = local_storage.get_download_url(release_obj.release_id + apptype,600,'plist')
download_url = self.get_download_url_by_cache(app_obj,release_id + apptype,600,isdownload)
res.data={"download_url":download_url}
return Response(res.dict)
@ -148,3 +146,24 @@ class InstallView(APIView):
res.code = 1006
res.msg = "该应用不存在"
return Response(res.dict)
def get_download_url_by_cache(self,app_obj,filename,limit,isdownload=False):
now = time.time()
download_val = cache.get("%s_%s" % ('download_url', filename))
if download_val:
if download_val.get("time") > now - 60:
return download_val.get("download_url")
else:
if isdownload:
local_storage = LocalStorage('localhost', False)
return local_storage.get_download_url(filename, limit, 'plist')
user_obj = UserInfo.objects.filter(pk=app_obj.get("user_id")).first()
storage = Storage(user_obj)
return storage.get_download_url(filename, limit)
def get_app_instance_by_cache(self,app_id,limit):
app_obj_cache = cache.get("%s_%s" % ('app_instance', app_id))
if not app_obj_cache:
app_obj_cache = Apps.objects.filter(app_id=app_id).values("pk",'user_id','type').first()
cache.set("%s_%s" % ('app_instance', app_id),app_obj_cache,limit)
return app_obj_cache

@ -231,7 +231,7 @@ class UploadView(APIView):
old_file_key = release_obj.icon_url
release_obj.icon_url = certinfo.get("upload_key")
release_obj.save()
del_cache_response_by_short(app_obj.short)
del_cache_response_by_short(app_obj.short,app_id)
storage.delete_file(old_file_key)
return Response(res.dict)
elif ftype and ftype == 'head':

Loading…
Cancel
Save