Skip to content

Commit 9af0acb

Browse files
committed
add api application
1 parent 8313b9e commit 9af0acb

12 files changed

Lines changed: 2654 additions & 8 deletions

File tree

ESSArch_TA/api/__init__.py

Whitespace-only changes.

ESSArch_TA/api/models.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import os
2+
import time
3+
import hashlib
4+
import uuid
5+
from django.db import models
6+
from django.core.files.uploadedfile import UploadedFile
7+
from django.core.files.storage import FileSystemStorage
8+
from django.utils import timezone
9+
from django.conf import settings
10+
from chunked_upload.models import CHUNKED_UPLOAD_CHOICES, UPLOADING, \
11+
AUTH_USER_MODEL, EXPIRATION_DELTA
12+
13+
def generate_upload_id():
14+
return uuid.uuid4().hex
15+
16+
class BaseChunkedUpload(models.Model):
17+
"""
18+
Base chunked upload model. This model is abstract (doesn't create a table
19+
in the database).
20+
Inherit from this model to implement your own.
21+
"""
22+
23+
upload_id = models.CharField(max_length=32, unique=True, editable=False,
24+
default=generate_upload_id)
25+
# The field "file" need to be defined in your own class to set attributes.
26+
#file = models.FileField(max_length=255, upload_to=generate_filename,
27+
# storage=STORAGE)
28+
filename = models.CharField(max_length=255)
29+
offset = models.BigIntegerField(default=0)
30+
created_on = models.DateTimeField(auto_now_add=True)
31+
status = models.PositiveSmallIntegerField(choices=CHUNKED_UPLOAD_CHOICES,
32+
default=UPLOADING)
33+
completed_on = models.DateTimeField(null=True, blank=True)
34+
35+
@property
36+
def expires_on(self):
37+
return self.created_on + EXPIRATION_DELTA
38+
39+
@property
40+
def expired(self):
41+
return self.expires_on <= timezone.now()
42+
43+
@property
44+
def md5(self):
45+
if getattr(self, '_md5', None) is None:
46+
md5 = hashlib.md5()
47+
for chunk in self.file.chunks():
48+
md5.update(chunk)
49+
self._md5 = md5.hexdigest()
50+
return self._md5
51+
52+
def delete(self, delete_file=True, *args, **kwargs):
53+
storage, path = self.file.storage, self.file.path
54+
super(BaseChunkedUpload, self).delete(*args, **kwargs)
55+
if delete_file:
56+
storage.delete(path)
57+
58+
def __unicode__(self):
59+
return u'<%s - upload_id: %s - bytes: %s - status: %s>' % (
60+
self.filename, self.upload_id, self.offset, self.status)
61+
62+
def close_file(self):
63+
"""
64+
Bug in django 1.4: FieldFile `close` method is not reaching all the
65+
way to the actual python file.
66+
Fix: we had to loop all inner files and close them manually.
67+
"""
68+
file_ = self.file
69+
while file_ is not None:
70+
file_.close()
71+
file_ = getattr(file_, 'file', None)
72+
73+
def append_chunk(self, chunk, chunk_size=None, save=True):
74+
self.close_file()
75+
self.file.open(mode='ab') # mode = append+binary
76+
# We can use .read() safely because chunk is already in memory
77+
self.file.write(chunk.read())
78+
if chunk_size is not None:
79+
self.offset += chunk_size
80+
elif hasattr(chunk, 'size'):
81+
self.offset += chunk.size
82+
else:
83+
self.offset = self.file.size
84+
self._md5 = None # Clear cached md5
85+
if save:
86+
self.save()
87+
self.close_file() # Flush
88+
89+
def get_uploaded_file(self):
90+
self.close_file()
91+
self.file.open(mode='rb') # mode = read+binary
92+
return UploadedFile(file=self.file, name=self.filename,
93+
size=self.offset)
94+
95+
class Meta:
96+
abstract = True
97+
98+
from django.db import ProgrammingError
99+
from configuration.models import Path
100+
101+
# GateareUpload
102+
try:
103+
Reception_upload_root = Path.objects.get(entity='path_ingest_reception').value
104+
except (Path.DoesNotExist, ProgrammingError) as e:
105+
Reception_upload_root = settings.MEDIA_ROOT
106+
107+
def Reception_filename(instance, filename):
108+
upload_path = os.path.join(Reception_upload_root,'chunked_uploads/%Y/%m/%d')
109+
filename = os.path.join(upload_path, instance.upload_id + '.part')
110+
return time.strftime(filename)
111+
112+
class Reception_storage(FileSystemStorage):
113+
def __init__(self):
114+
super(Reception_storage, self).__init__(location=Reception_upload_root)
115+
116+
class ReceptionUpload(BaseChunkedUpload):
117+
file = models.FileField(max_length=255, upload_to=Reception_filename,
118+
storage=Reception_storage())
119+
user = models.ForeignKey(AUTH_USER_MODEL, blank=True)
120+
121+
# Override the default ChunkedUpload to make the `user` field nullable
122+
#TmpWorkareaUpload._meta.get_field('user').null = True
123+
#TmpWorkareaUpload._meta.get_field('file').upload_to = generate_filename2
124+
125+

0 commit comments

Comments
 (0)