SuspiciousOperation using sorl-thumbnail
我有一个Django Web应用程序,可以代表用户访问和操纵多个服务器文件系统(例如/ fs01,/ fs02等)。我想将这些文件系统上的图像的缩略图呈现给用户,并且认为sole-thumbnail将是这样做的方法。
似乎图像必须在MEDIA_ROOT下,才能通过缩略图创建缩略图。我的
1 2 3 4 5 6 7 | path ="/Users/me/Dev/MyProject/myproj/media/pipe-img/magritte-pipe-large.jpg" try: im = get_thumbnail(path, '100x100', crop='center', quality=99) except Exception, e: exc_type, exc_obj, exc_tb = sys.exc_info() print"Failed getting thumbnail: (%s) %s" % (exc_type, e) print"im.url = %s" % im.url |
如我所料,它会创建缩略图并打印im.url。但是当我将
1 | path ="/fs02/dir/ep340102/foo/2048x1024/magritte-pipe-large.jpg" |
它失败并显示:
1 2 | Failed getting thumbnail: (<class 'django.core.exceptions.SuspiciousOperation'>) Attempted access to '/fs02/dir/ep340102/foo/2048x1024/magritte-pipe-large.jpg' denied. |
有没有办法解决这个问题?我可以使用sorl-thumbnail在其他文件系统(例如/ fs01,/ fs02,/ fs03等)下创建缩略图吗?有更好的方法吗?
更新。这是完整的堆栈跟踪:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | Environment: Request Method: GET Request URL: http://localhost:8000/pipe/file_selection/ Django Version: 1.4.1 Python Version: 2.7.2 Installed Applications: ('django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.admin', 'django.contrib.admindocs', 'django.contrib.humanize', 'django.contrib.messages', 'pipeproj.pipe', 'south', 'guardian', 'sorl.thumbnail') Installed Middleware: ('django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware') Traceback: File"/Library/Python/2.7/site-packages/django/core/handlers/base.py" in get_response 111. response = callback(request, *callback_args, **callback_kwargs) File"/Library/Python/2.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view 20. return view_func(request, *args, **kwargs) File"/Users/dylan/Dev/Pipe/pipeproj/../pipeproj/pipe/views/data.py" in file_selection 184. im = get_thumbnail(path, '100x100', crop='center', quality=99) File"/Library/Python/2.7/site-packages/sorl_thumbnail-11.12-py2.7.egg/sorl/thumbnail/shortcuts.py" in get_thumbnail 8. return default.backend.get_thumbnail(file_, geometry_string, **options) File"/Library/Python/2.7/site-packages/sorl_thumbnail-11.12-py2.7.egg/sorl/thumbnail/base.py" in get_thumbnail 56. source_image = default.engine.get_image(source) File"/Library/Python/2.7/site-packages/sorl_thumbnail-11.12-py2.7.egg/sorl/thumbnail/engines/pil_engine.py" in get_image 12. buf = StringIO(source.read()) File"/Library/Python/2.7/site-packages/sorl_thumbnail-11.12-py2.7.egg/sorl/thumbnail/images.py" in read 121. return self.storage.open(self.name).read() File"/Library/Python/2.7/site-packages/django/core/files/storage.py" in open 33. return self._open(name, mode) File"/Library/Python/2.7/site-packages/django/core/files/storage.py" in _open 156. return File(open(self.path(name), mode)) File"/Library/Python/2.7/site-packages/django/core/files/storage.py" in path 246. raise SuspiciousOperation("Attempted access to '%s' denied." % name) Exception Type: SuspiciousOperation at /pipe/file_selection/ Exception Value: Attempted access to '/fs02/dir/ep340102/foo/2048x1024/bettina.jpg' denied. |
SuspiciousOperation来自FileSystemStorage.path(),位于:
1 2 3 4 5 6 | def path(self, name): try: path = safe_join(self.location, name) except ValueError: raise SuspiciousFileOperation("Attempted access to '%s' denied." % name) return os.path.normpath(path) |
它源自具有以下测试的safe_join():
1 2 | if (not normcase(final_path).startswith(normcase(base_path + sep)) and ... |
这意味着计算出的文件名必须存在于配置的缩略图存储中。默认情况下为settings.THUMBNAIL_STORAGE是settings.DEFAULT_FILE_STORAGE是FileSystemStorage,用于将文件存储在settings.MEDIA_ROOT中。
通过定义存储类别,您应该能够为缩略图使用其他存储路径:
1 2 3 4 5 6 | from django.core.files.storage import FileSystemStorage class ThumbnailStorage(FileSystemStorage): def __init__(self, **kwargs): super(ThumbnailStorage, self).__init__( location='/fs02', base_url='/fs02') |
然后在settings.py
中
1 | THUMBNAIL_STORAGE = 'myproj.storage.ThumbnailStorage' |
您还需要确保在该URL上正在/ fs02提供服务:
1 2 3 4 | if settings.DEBUG: patterns += patterns('', url(r'^fs02/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/fs02'})) |
请注意,您的缩略图将根据默认的THUMBNAIL_PREFIX
创建为/ fs02 / cache / ...
我是通过提供一个绝对URL来做到这一点的,就像这样:
1 2 3 4 5 | from sorl.thumbnail import get_thumbnail from django.contrib.staticfiles.storage import staticfiles_storage image_url = staticfiles_storage.url('image.jpg') thumbnail = get_thumbnail(image_url, '100x100') |
使用以下命令会得到什么?
1 | ls -la /fs02/dir/ep340102/foo/2048x1024/ |
如果文件所有者不是好的所有者(和/或错误的文件权限),通常会发生拒绝访问的情况。