2013-02-11 71 views
2

我有訪問和操縱代表用戶的幾個服務器的文件系統(例如/ FS01,/ FS02等)一個Django web應用程序。我想向用戶展示這些文件系統上的圖像縮略圖,並認爲sorl-thumbnail是實現它的方式。SuspiciousOperation使用SORL縮略圖

看來,雖然這些圖像必須在MEDIA_ROOT爲SORL-縮略圖創建縮略圖。我MEDIA_ROOT/Users/me/Dev/MyProject/myproj/media,所以此工程:

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,如我所期待。但是,當我改變path到:

path = "/fs02/dir/ep340102/foo/2048x1024/magritte-pipe-large.jpg" 

它失敗:

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等)?有更好的方法嗎?

更新。以下是完整的堆棧跟蹤:

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. 
+0

我認爲你應該使用相對路徑'settings.MEDIA_ROOT'代替絕對路徑。但是完整的堆棧跟蹤對於做出準確的答案會很有用。 – jpic 2013-02-11 21:21:08

+0

我只是爲了說明目的而包括實際路徑。我可以將'path'設置爲'os.path.join(settings.MEDIA_ROOT,「pipe-img/magritte-pipe-large.jpg」)'。好主意 - 我現在將添加完整的堆棧跟蹤。 – mobopro 2013-02-11 21:44:26

+0

嘗試''pipe-img/magritte-pipe-large.jpg「'而不是'os.path.join(settings.MEDIA_ROOT,」pipe-img/magritte-pipe-large.jpg「)''。我認爲它會自動生成絕對路徑。 – jpic 2013-02-12 09:02:36

回答

4

的SuspiciousOperation是FileSystemStorage.path()位置:

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()具有這種測試:

if (not normcase(final_path).startswith(normcase(base_path + sep)) and 
... 

這意味着計算出的文件名必須存在於配置的縮略圖存儲器中。默認情況下,settings.THUMBNAIL_STORAGE是settings.DEFAULT_FILE_STORAGE,它是將文件存儲在settings.MEDIA_ROOT中的FileSystemStorage。

您應該能夠通過定義存儲類用於縮略圖不同的存儲路徑:

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

THUMBNAIL_STORAGE = 'myproj.storage.ThumbnailStorage' 

您還需要確保東西在服務/ fs02在該URL:

if settings.DEBUG: 
    patterns += patterns('', 
     url(r'^fs02/(?P<path>.*)$', 'django.views.static.serve', 
      {'document_root': '/fs02'})) 

請注意,您的縮略圖將被創建爲/ fs 02 /緩存/ ...每默認THUMBNAIL_PREFIX

+0

我最終走了一個不同於sorl-thumbnail的方向,但是當我有這個答案的時候,我會用它。看起來很對我! – mobopro 2013-08-29 15:36:00

0

用下面的命令得到了什麼?

ls -la /fs02/dir/ep340102/foo/2048x1024/ 

訪問通常拒絕發生,如果該文件所有者不是一個好(和/或錯誤的文件權限)...

+0

不,我確定文件是可以訪問的......'-rw-rw-rw- @ 1 dylan staff 82222 Feb 6 06:28 magritte-pipe-large.jpg'。我一直在挖掘storage.py代碼,並認爲我有一個想法是什麼。更多... – mobopro 2013-02-12 04:26:08

+0

ls -la/fs02?我有一個文件可以訪問的情況下,但不是其目錄的鏈接... – 2013-02-12 05:46:56

0

我做到了通過提供一個絕對的URL,而不是像這樣:

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')