file md5

Brightcells 8 年之前
父節點
當前提交
ae70dce3ef
共有 9 個文件被更改,包括 194 次插入91 次删除
  1. 15 41
      group/lensman_views.py
  2. 3 3
      group/tourguidegroup_views.py
  3. 11 27
      group/views.py
  4. 1 1
      photo/admin.py
  5. 69 0
      photo/migrations/0011_auto_20170119_1207.py
  6. 15 0
      photo/models.py
  7. 3 10
      photo/views.py
  8. 1 1
      requirements.txt
  9. 76 8
      utils/storage_utils.py

+ 15 - 41
group/lensman_views.py

@@ -178,58 +178,32 @@ def lensman_photo_upload_api(request):
178 178
 
179 179
     if photo and r.acquire_lock('{}:{}:{}'.format(group_id, user_id, photo.name), time=60):
180 180
         # 写 PhotosInfo 表
181
-        m_photo_path, ext = file_save(photo, prefix='photo', ext='jpeg')
182
-        p_photo_path = 'photo/{}{}'.format(shortuuid.uuid(), ext)
183
-        watermark_wrap(
184
-            os.path.join(settings.MEDIA_ROOT, m_photo_path).replace('\\', '/'),
185
-            settings.WATERMARK_LOGO,
186
-            os.path.join(settings.MEDIA_ROOT, p_photo_path).replace('\\', '/')
187
-        )
181
+        photo_info = file_save(photo, prefix='photo', ext='jpeg', watermark=True, thumbnail=True)
188 182
 
189 183
         photo, created = PhotosInfo.objects.get_or_create(
190 184
             lensman_id=lensman_id,
191 185
             session_id=session_id,
192 186
             photo_id=photo_id,
193 187
         )
194
-        photo.p_photo_path = p_photo_path
195
-        photo.m_photo_path = m_photo_path
188
+        photo.m_photo_path = photo_info.photo_path
189
+        photo.p_photo_path = photo_info.photo_watermark_path
196 190
         photo.save()
197 191
 
198 192
         # 写 GroupPhotoInfo 表
199
-        photo_path = photo.p_photo_path
200
-        photo_thumbnail_path = photo_path.replace('.', '_thumbnail.')
201
-        photo_thumbnail2_path = photo_path.replace('.', '_thumbnail2.')
202
-
203
-        # 群组照片缩略图生成
204
-        # 双列: 540, 40-50K
205
-        photo_w, photo_h, photo_thumbnail_w, photo_thumbnail_h = make_thumbnail(
206
-            os.path.join(settings.MEDIA_ROOT, photo_path).replace('\\', '/'),
207
-            os.path.join(settings.MEDIA_ROOT, photo_thumbnail_path).replace('\\', '/'),
208
-            settings.THUMBNAIL_MAX_WIDTH
209
-        )
210
-
211
-        # 单列: 1080, xx-100K
212
-        photo_w, photo_h, photo_thumbnail2_w, photo_thumbnail2_h = make_thumbnail(
213
-            os.path.join(settings.MEDIA_ROOT, photo_path).replace('\\', '/'),
214
-            os.path.join(settings.MEDIA_ROOT, photo_thumbnail2_path).replace('\\', '/'),
215
-            settings.THUMBNAIL_MAX_WIDTH2
216
-        )
217
-
218
-        # 群组照片记录创建
219 193
         group_photo = GroupPhotoInfo.objects.create(
220 194
             group_id=group_id,
221 195
             user_id=user_id,
222 196
             nickname=user.final_nickname,
223 197
             avatar=user.avatar,
224
-            photo_path=photo_path,
225
-            photo_w=photo_w,
226
-            photo_h=photo_h,
227
-            photo_thumbnail_path=photo_thumbnail_path,
228
-            photo_thumbnail_w=photo_thumbnail_w,
229
-            photo_thumbnail_h=photo_thumbnail_h,
230
-            photo_thumbnail2_path=photo_thumbnail2_path,
231
-            photo_thumbnail2_w=photo_thumbnail2_w,
232
-            photo_thumbnail2_h=photo_thumbnail2_h,
198
+            photo_path=photo_info.photo_path,
199
+            photo_w=photo_info.photo_w,
200
+            photo_h=photo_info.photo_h,
201
+            photo_thumbnail_path=photo_info.photo_thumbnail_path,
202
+            photo_thumbnail_w=photo_info.photo_thumbnail_w,
203
+            photo_thumbnail_h=photo_info.photo_thumbnail_h,
204
+            photo_thumbnail2_path=photo_info.photo_thumbnail2_path,
205
+            photo_thumbnail2_w=photo_info.photo_thumbnail2_w,
206
+            photo_thumbnail2_h=photo_info.photo_thumbnail2_h,
233 207
             photo_from=GroupPhotoInfo.SESSION_GROUP,
234 208
             session_id=photo.session_id,
235 209
             lensman_id=photo.lensman_id,
@@ -320,14 +294,14 @@ def lensman_origin_photo_upload_api(request):
320 294
 
321 295
     if photo and r.acquire_lock('{}:{}:{}'.format(order_id, user_id, photo.name), time=60):
322 296
         # 写 PhotosInfo 表
323
-        r_photo_path, ext = file_save(photo, prefix='photo', ext='jpeg')
297
+        photo_info = file_save(photo, prefix='photo', ext='jpeg')
324 298
 
325 299
         PhotosInfo.objects.filter(
326 300
             lensman_id=lensman_id,
327 301
             session_id=session_id,
328 302
             photo_id=photo_id,
329 303
         ).update(
330
-            r_photo_path=r_photo_path
304
+            r_photo_path=photo_info.photo_path
331 305
         )
332 306
 
333 307
         porder, created = GroupPhotoOrderInfo.objects.select_for_update().get_or_create(
@@ -337,7 +311,7 @@ def lensman_origin_photo_upload_api(request):
337 311
             photo_id=order.photo_id,
338 312
             lensman_photo_id=photo_id,
339 313
         )
340
-        porder.r_photo_path = r_photo_path
314
+        porder.r_photo_path = photo_info.photo_path
341 315
         porder.save()
342 316
 
343 317
         set_lensman_order_record(porder)

+ 3 - 3
group/tourguidegroup_views.py

@@ -189,7 +189,7 @@ def tg_group_update_api(request):
189 189
         group.group_desc = group_desc
190 190
     # 群组头像更新
191 191
     if group_avatar:
192
-        group.group_avatar = file_save(group_avatar, prefix='group', ext='jpeg')[0]
192
+        group.group_avatar = file_save(group_avatar, prefix='group', ext='jpeg').photo_path
193 193
     # 起止时间更新
194 194
     if started_at:
195 195
         group.started_at = started_at
@@ -200,10 +200,10 @@ def tg_group_update_api(request):
200 200
         group.total_persons = total_persons
201 201
     # 注意事项更新
202 202
     if attentions:
203
-        group.attentions_path = file_save(attentions, prefix='tour', ext='jpeg')[0]
203
+        group.attentions_path = file_save(attentions, prefix='tour', ext='jpeg').photo_path
204 204
     # 行程安排更新
205 205
     if schedules:
206
-        group.schedules_path = file_save(schedules, prefix='tour', ext='jpeg')[0]
206
+        group.schedules_path = file_save(schedules, prefix='tour', ext='jpeg').photo_path
207 207
     group.save()
208 208
 
209 209
     # Redis 群组数据缓存更新

+ 11 - 27
group/views.py

@@ -134,7 +134,7 @@ def group_update_api(request):
134 134
         group.group_desc = group_desc
135 135
     # 群组头像更新
136 136
     if group_avatar:
137
-        group.group_avatar = file_save(group_avatar, prefix='group', ext='jpeg')[0]
137
+        group.group_avatar = file_save(group_avatar, prefix='group', ext='jpeg').photo_path
138 138
     group.save()
139 139
 
140 140
     # Redis 群组数据缓存更新
@@ -254,23 +254,7 @@ def flyimg_upload_api(request):
254 254
         return response(GroupUserStatusCode.GROUP_USER_NOT_FOUND)
255 255
 
256 256
     if photo and r.acquire_lock('{}:{}:{}'.format(group_id, user_id, photo.name), time=60):
257
-        photo_path, ext = file_save(photo, prefix='fly', ext='jpeg')
258
-        photo_thumbnail_path = photo_path.replace('.', '_thumbnail.')
259
-        photo_thumbnail2_path = photo_path.replace('.', '_thumbnail2.')
260
-
261
-        # 群组照片缩略图生成
262
-        # 双列: 540, 40-50K
263
-        photo_w, photo_h, photo_thumbnail_w, photo_thumbnail_h = make_thumbnail(
264
-            os.path.join(settings.MEDIA_ROOT, photo_path).replace('\\', '/'),
265
-            os.path.join(settings.MEDIA_ROOT, photo_thumbnail_path).replace('\\', '/'),
266
-            settings.THUMBNAIL_MAX_WIDTH
267
-        )
268
-        # 单列: 1080, xx-100K
269
-        photo_w, photo_h, photo_thumbnail2_w, photo_thumbnail2_h = make_thumbnail(
270
-            os.path.join(settings.MEDIA_ROOT, photo_path).replace('\\', '/'),
271
-            os.path.join(settings.MEDIA_ROOT, photo_thumbnail2_path).replace('\\', '/'),
272
-            settings.THUMBNAIL_MAX_WIDTH2
273
-        )
257
+        photo_info = file_save(photo, prefix='fly', ext='jpeg', thumbnail=True)
274 258
 
275 259
         # 群组照片记录创建
276 260
         group_photo = GroupPhotoInfo.objects.create(
@@ -278,15 +262,15 @@ def flyimg_upload_api(request):
278 262
             user_id=user_id,
279 263
             nickname=nickname or user.final_nickname,
280 264
             avatar=user.avatar,
281
-            photo_path=photo_path,
282
-            photo_w=photo_w,
283
-            photo_h=photo_h,
284
-            photo_thumbnail_path=photo_thumbnail_path,
285
-            photo_thumbnail_w=photo_thumbnail_w,
286
-            photo_thumbnail_h=photo_thumbnail_h,
287
-            photo_thumbnail2_path=photo_thumbnail2_path,
288
-            photo_thumbnail2_w=photo_thumbnail2_w,
289
-            photo_thumbnail2_h=photo_thumbnail2_h,
265
+            photo_path=photo_info.photo_path,
266
+            photo_w=photo_info.photo_w,
267
+            photo_h=photo_info.photo_h,
268
+            photo_thumbnail_path=photo_info.photo_thumbnail_path,
269
+            photo_thumbnail_w=photo_info.photo_thumbnail_w,
270
+            photo_thumbnail_h=photo_info.photo_thumbnail_h,
271
+            photo_thumbnail2_path=photo_info.photo_thumbnail2_path,
272
+            photo_thumbnail2_w=photo_info.photo_thumbnail2_w,
273
+            photo_thumbnail2_h=photo_info.photo_thumbnail2_h,
290 274
         )
291 275
 
292 276
         # 设置群组最后一张照片PK

+ 1 - 1
photo/admin.py

@@ -11,7 +11,7 @@ class UUIDInfoAdmin(admin.ModelAdmin):
11 11
 
12 12
 
13 13
 class PhotoUUIDInfoAdmin(admin.ModelAdmin):
14
-    list_display = ('photo_md5', 'photo_path', 'status', 'created_at', 'updated_at')
14
+    list_display = ('photo_md5', 'photo_path', 'photo_watermark_path', 'photo_thumbnail_path', 'photo_thumbnail2_path', 'status', 'created_at', 'updated_at')
15 15
     list_filter = ('status', )
16 16
 
17 17
 

+ 69 - 0
photo/migrations/0011_auto_20170119_1207.py

@@ -0,0 +1,69 @@
1
+# -*- coding: utf-8 -*-
2
+from __future__ import unicode_literals
3
+
4
+from django.db import models, migrations
5
+
6
+
7
+class Migration(migrations.Migration):
8
+
9
+    dependencies = [
10
+        ('photo', '0010_photouuidinfo'),
11
+    ]
12
+
13
+    operations = [
14
+        migrations.AddField(
15
+            model_name='photouuidinfo',
16
+            name='photo_h',
17
+            field=models.IntegerField(default=0, help_text='\u7167\u7247\u9ad8\u5ea6', verbose_name='photo_h'),
18
+        ),
19
+        migrations.AddField(
20
+            model_name='photouuidinfo',
21
+            name='photo_thumbnail2_h',
22
+            field=models.IntegerField(default=0, help_text='\u7167\u7247\u7f29\u7565\u56fe\u9ad8\u5ea6', verbose_name='photo_thumbnail2_h'),
23
+        ),
24
+        migrations.AddField(
25
+            model_name='photouuidinfo',
26
+            name='photo_thumbnail2_path',
27
+            field=models.CharField(help_text='\u7167\u7247\u7f29\u7565\u56fe\u5b58\u653e\u8def\u5f84', max_length=255, null=True, verbose_name='photo_thumbnail2_path', blank=True),
28
+        ),
29
+        migrations.AddField(
30
+            model_name='photouuidinfo',
31
+            name='photo_thumbnail2_w',
32
+            field=models.IntegerField(default=0, help_text='\u7167\u7247\u7f29\u7565\u56fe\u5bbd\u5ea6', verbose_name='photo_thumbnail2_w'),
33
+        ),
34
+        migrations.AddField(
35
+            model_name='photouuidinfo',
36
+            name='photo_thumbnail_h',
37
+            field=models.IntegerField(default=0, help_text='\u7167\u7247\u7f29\u7565\u56fe\u9ad8\u5ea6', verbose_name='photo_thumbnail_h'),
38
+        ),
39
+        migrations.AddField(
40
+            model_name='photouuidinfo',
41
+            name='photo_thumbnail_path',
42
+            field=models.CharField(help_text='\u7167\u7247\u7f29\u7565\u56fe\u5b58\u653e\u8def\u5f84', max_length=255, null=True, verbose_name='photo_thumbnail_path', blank=True),
43
+        ),
44
+        migrations.AddField(
45
+            model_name='photouuidinfo',
46
+            name='photo_thumbnail_w',
47
+            field=models.IntegerField(default=0, help_text='\u7167\u7247\u7f29\u7565\u56fe\u5bbd\u5ea6', verbose_name='photo_thumbnail_w'),
48
+        ),
49
+        migrations.AddField(
50
+            model_name='photouuidinfo',
51
+            name='photo_w',
52
+            field=models.IntegerField(default=0, help_text='\u7167\u7247\u5bbd\u5ea6', verbose_name='photo_w'),
53
+        ),
54
+        migrations.AddField(
55
+            model_name='photouuidinfo',
56
+            name='photo_watermark_h',
57
+            field=models.IntegerField(default=0, help_text='\u7167\u7247\u6c34\u5370\u56fe\u9ad8\u5ea6', verbose_name='photo_watermark_h'),
58
+        ),
59
+        migrations.AddField(
60
+            model_name='photouuidinfo',
61
+            name='photo_watermark_path',
62
+            field=models.CharField(help_text='\u7167\u7247\u5b58\u653e\u8def\u5f84\uff0cBox\u4e0a\u4f20\uff0c\u6709\u6c34\u5370\uff0c\u670d\u52a1\u5668\u6dfb\u52a0', max_length=255, null=True, verbose_name='photo_watermark_path', blank=True),
63
+        ),
64
+        migrations.AddField(
65
+            model_name='photouuidinfo',
66
+            name='photo_watermark_w',
67
+            field=models.IntegerField(default=0, help_text='\u7167\u7247\u6c34\u5370\u56fe\u5bbd\u5ea6', verbose_name='photo_watermark_w'),
68
+        ),
69
+    ]

+ 15 - 0
photo/models.py

@@ -29,7 +29,22 @@ class UUIDInfo(CreateUpdateMixin):
29 29
 
30 30
 class PhotoUUIDInfo(CreateUpdateMixin):
31 31
     photo_md5 = models.CharField(_(u'photo_md5'), max_length=255, blank=True, null=True, help_text=u'照片唯一标识', db_index=True, unique=True)
32
+
32 33
     photo_path = models.CharField(_(u'photo_path'), max_length=255, blank=True, null=True, help_text=u'照片路径')
34
+    photo_w = models.IntegerField(_(u'photo_w'), default=0, help_text=u'照片宽度')
35
+    photo_h = models.IntegerField(_(u'photo_h'), default=0, help_text=u'照片高度')
36
+
37
+    photo_watermark_path = models.CharField(_(u'photo_watermark_path'), max_length=255, blank=True, null=True, help_text=u'照片存放路径,Box上传,有水印,服务器添加')
38
+    photo_watermark_w = models.IntegerField(_(u'photo_watermark_w'), default=0, help_text=u'照片水印图宽度')
39
+    photo_watermark_h = models.IntegerField(_(u'photo_watermark_h'), default=0, help_text=u'照片水印图高度')
40
+
41
+    photo_thumbnail_path = models.CharField(_(u'photo_thumbnail_path'), max_length=255, blank=True, null=True, help_text=u'照片缩略图存放路径')
42
+    photo_thumbnail_w = models.IntegerField(_(u'photo_thumbnail_w'), default=0, help_text=u'照片缩略图宽度')
43
+    photo_thumbnail_h = models.IntegerField(_(u'photo_thumbnail_h'), default=0, help_text=u'照片缩略图高度')
44
+
45
+    photo_thumbnail2_path = models.CharField(_(u'photo_thumbnail2_path'), max_length=255, blank=True, null=True, help_text=u'照片缩略图存放路径')
46
+    photo_thumbnail2_w = models.IntegerField(_(u'photo_thumbnail2_w'), default=0, help_text=u'照片缩略图宽度')
47
+    photo_thumbnail2_h = models.IntegerField(_(u'photo_thumbnail2_h'), default=0, help_text=u'照片缩略图高度')
33 48
 
34 49
     class Meta:
35 50
         verbose_name = _('photouuidinfo')

+ 3 - 10
photo/views.py

@@ -91,21 +91,14 @@ def upload_photo(request):
91 91
     except LensmanInfo.DoesNotExist:
92 92
         return response(LensmanStatusCode.LENSMAN_NOT_FOUND)
93 93
 
94
-    m_photo_path, ext = file_save(photo, prefix='photo', ext='jpeg')
95
-
96
-    p_photo_path = 'photo/{}{}'.format(shortuuid.uuid(), ext)
97
-    watermark_wrap(
98
-        os.path.join(settings.MEDIA_ROOT, m_photo_path).replace('\\', '/'),
99
-        settings.WATERMARK_LOGO,
100
-        os.path.join(settings.MEDIA_ROOT, p_photo_path).replace('\\', '/')
101
-    )
94
+    photo_info = file_save(photo, prefix='photo', ext='jpeg', watermark=True)
102 95
 
103 96
     photo, created = PhotosInfo.objects.get_or_create(
104 97
         lensman_id=lensman_id,
105 98
         session_id=session_id,
106 99
         photo_id=photo_id,
107
-        p_photo_path=p_photo_path,
108
-        m_photo_path=m_photo_path,
100
+        p_photo_path=photo_info.photo_watermark_path,
101
+        m_photo_path=photo_info.photo_path,
109 102
     )
110 103
 
111 104
     return response(200, 'Photo Upload Success', u'照片上传成功', photo.data)

+ 1 - 1
requirements.txt

@@ -29,7 +29,7 @@ mock==2.0.0
29 29
 pep8==1.7.0
30 30
 pywe-oauth==1.0.2
31 31
 records==0.4.3
32
-redis-extensions==1.0.36
32
+redis-extensions==1.0.37
33 33
 requests==2.12.4
34 34
 rlog==0.2
35 35
 shortuuid==0.4.3

+ 76 - 8
utils/storage_utils.py

@@ -3,26 +3,94 @@
3 3
 import os
4 4
 
5 5
 import shortuuid
6
+from django.conf import settings
6 7
 from django.core.files.storage import default_storage
7 8
 from django.db import transaction
8 9
 from filemd5 import calculate_md5
9 10
 
10 11
 from photo.models import PhotoUUIDInfo
12
+from utils.thumbnail_utils import make_thumbnail
13
+from utils.watermark_utils import watermark_wrap
14
+
15
+
16
+class DotDict(dict):
17
+    """ dot.notation access to dictionary attributes """
18
+    def __getattr__(self, attr):
19
+        return self.get(attr)
20
+    __setattr__ = dict.__setitem__
21
+    __delattr__ = dict.__delitem__
11 22
 
12 23
 
13 24
 @transaction.atomic
14
-def file_save(file_, prefix='img', ext='jpeg'):
25
+def file_save(file_, prefix='img', ext='jpeg', watermark=False, thumbnail=False):
15 26
     ext = os.path.splitext(file_.name)[-1] or ext
16 27
 
17 28
     photo, created = PhotoUUIDInfo.objects.select_for_update().get_or_create(photo_md5=calculate_md5(file_))
18 29
 
19
-    if not photo.photo_path:
20
-        path = '{}/{}{}'.format(prefix, shortuuid.uuid(), ext)
21
-        if default_storage.exists(path):
22
-            default_storage.delete(path)
23
-        default_storage.save(path, file_)
30
+    photo_path = photo.photo_path
31
+    if not photo_path:
32
+        photo_path = '{}/{}{}'.format(prefix, shortuuid.uuid(), ext)
33
+        if default_storage.exists(photo_path):
34
+            default_storage.delete(photo_path)
35
+        default_storage.save(photo_path, file_)
36
+
37
+        photo.photo_path = photo_path
38
+        photo.save()
39
+
40
+    if watermark:
41
+        if not photo.photo_watermark_path:
42
+            photo_watermark_path = 'photo/{}{}'.format(shortuuid.uuid(), ext)
43
+            watermark_wrap(
44
+                os.path.join(settings.MEDIA_ROOT, photo_path).replace('\\', '/'),
45
+                settings.WATERMARK_LOGO,
46
+                os.path.join(settings.MEDIA_ROOT, photo_watermark_path).replace('\\', '/')
47
+            )
48
+            photo.photo_watermark_path
49
+            photo.save()
24 50
 
25
-        photo.photo_path = path
51
+    if thumbnail:
52
+        if not photo.photo_thumbnail_path:
53
+            # 双列: 540, 40-50K
54
+            photo_thumbnail_path = photo_path.replace('.', '_thumbnail.')
55
+            photo_w, photo_h, photo_thumbnail_w, photo_thumbnail_h = make_thumbnail(
56
+                os.path.join(settings.MEDIA_ROOT, photo_path).replace('\\', '/'),
57
+                os.path.join(settings.MEDIA_ROOT, photo_thumbnail_path).replace('\\', '/'),
58
+                settings.THUMBNAIL_MAX_WIDTH
59
+            )
60
+            photo.photo_w = photo_w
61
+            photo.photo_h = photo_h
62
+            photo.photo_thumbnail_path = photo_thumbnail_path
63
+            photo.photo_thumbnail_w = photo_thumbnail_w
64
+            photo.photo_thumbnail_h = photo_thumbnail_h
65
+        if not photo.photo_thumbnail2_path:
66
+            # 单列: 1080, xx-100K
67
+            photo_thumbnail2_path = photo_path.replace('.', '_thumbnail2.')
68
+            photo_w, photo_h, photo_thumbnail2_w, photo_thumbnail2_h = make_thumbnail(
69
+                os.path.join(settings.MEDIA_ROOT, photo_path).replace('\\', '/'),
70
+                os.path.join(settings.MEDIA_ROOT, photo_thumbnail2_path).replace('\\', '/'),
71
+                settings.THUMBNAIL_MAX_WIDTH2
72
+            )
73
+            photo.photo_w = photo_w
74
+            photo.photo_h = photo_h
75
+            photo.photo_thumbnail2_path = photo_thumbnail2_path
76
+            photo.photo_thumbnail2_w = photo_thumbnail2_w
77
+            photo.photo_thumbnail2_h = photo_thumbnail2_h
26 78
         photo.save()
27 79
 
28
-    return photo.photo_path, ext
80
+    return DotDict({
81
+        'ext': ext,
82
+
83
+        'photo_path': photo_path,
84
+        'photo_w': photo.photo_w,
85
+        'photo_h': photo.photo_h,
86
+
87
+        'photo_watermark_path': photo.photo_watermark_path,
88
+
89
+        'photo_thumbnail_path': photo.photo_thumbnail_path,
90
+        'photo_thumbnail_w': photo.photo_thumbnail_w,
91
+        'photo_thumbnail_h': photo.photo_thumbnail_h,
92
+
93
+        'photo_thumbnail2_path': photo.photo_thumbnail2_path,
94
+        'photo_thumbnail2_w': photo.photo_thumbnail2_w,
95
+        'photo_thumbnail2_h': photo.photo_thumbnail2_h,
96
+    })