93 lines
3.1 KiB
Python
93 lines
3.1 KiB
Python
import os
|
|
|
|
from django.core.files.storage import Storage
|
|
from django.utils.encoding import force_unicode
|
|
|
|
from pymongo import Connection
|
|
from gridfs import GridFS
|
|
|
|
from storage.conf import settings
|
|
|
|
|
|
class GridFSStorage(Storage):
|
|
separator = u'/'
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.db = Connection(host=settings.GRIDFS_HOST,
|
|
port=settings.GRIDFS_PORT)[settings.GRIDFS_DATABASE_NAME]
|
|
self.fs = GridFS(self.db)
|
|
|
|
def save(self, name, content):
|
|
#TODO: if exists add _ plus a counter
|
|
while True:
|
|
try:
|
|
# This file has a file path that we can move.
|
|
if hasattr(content, 'temporary_file_path'):
|
|
self.move(content.temporary_file_path(), name)
|
|
content.close()
|
|
# This is a normal uploadedfile that we can stream.
|
|
else:
|
|
# This fun binary flag incantation makes os.open throw an
|
|
# OSError if the file already exists before we open it.
|
|
newfile = self.fs.new_file(filename=name)
|
|
try:
|
|
for chunk in content.chunks():
|
|
newfile.write(chunk)
|
|
finally:
|
|
newfile.close()
|
|
except Exception, e: # OSError, e:
|
|
# if e.errno == errno.EEXIST:
|
|
# # Ooops, the file exists. We need a new file name.
|
|
# name = self.get_available_name(name)
|
|
# full_path = self.path(name)
|
|
# else:
|
|
# raise
|
|
raise
|
|
else:
|
|
# OK, the file save worked. Break out of the loop.
|
|
break
|
|
|
|
return name
|
|
|
|
def open(self, name, *args, **kwars):
|
|
return self.fs.get_last_version(name)
|
|
|
|
def delete(self, name):
|
|
oid = self.fs.get_last_version(name)._id
|
|
self.fs.delete(oid)
|
|
|
|
def exists(self, name):
|
|
return self.fs.exists(filename=name)
|
|
|
|
def path(self, name):
|
|
return force_unicode(name)
|
|
|
|
def size(self, name):
|
|
return self.fs.get_last_version(name).length
|
|
|
|
def move(self, old_file_name, name, chunk_size=1024 * 64):
|
|
# first open the old file, so that it won't go away
|
|
old_file = open(old_file_name, 'rb')
|
|
try:
|
|
newfile = self.fs.new_file(filename=name)
|
|
|
|
try:
|
|
current_chunk = None
|
|
while current_chunk != '':
|
|
current_chunk = old_file.read(chunk_size)
|
|
newfile.write(current_chunk)
|
|
finally:
|
|
newfile.close()
|
|
finally:
|
|
old_file.close()
|
|
|
|
try:
|
|
os.remove(old_file_name)
|
|
except OSError, e:
|
|
# Certain operating systems (Cygwin and Windows)
|
|
# fail when deleting opened files, ignore it. (For the
|
|
# systems where this happens, temporary files will be auto-deleted
|
|
# on close anyway.)
|
|
if getattr(e, 'winerror', 0) != 32 and getattr(e, 'errno', 0) != 13:
|
|
raise
|