2009-12-23 69 views
26

我試圖刪除上傳的圖片時遇到了問題。可疑操作Django

的錯誤是沿着這些線路:

SuspiciousOperation: Attempted access to '/media/artists/12-stones/154339.jpg' denied. 

讀圍繞它看起來像錯誤後是由於這樣的事實,它在尋找在錯誤的地方的圖像(注意第一個斜槓,/媒體/沒有按「T在文件系統中存在)

我MEDIA_ROOT和MEDIA_URL是:

MEDIA_ROOT = '/home/tsoporan/site/media/' 
MEDIA_URL = "/media/ 

我的模型upload_to參數傳遞這個函數:

def get_artist_path(instance, filename): 
    return os.path.join('artists', slugify(instance.name), filename) 

我的問題是:

1)我怎樣才能解決這個問題,爲今後的上傳?

2)是否有可能修復我當前的圖像的路徑,而無需重新上傳?

問候, 泰特斯

+0

你是如何提供靜態文件嗎?你使用什麼URL來處理靜態文件。 – czarchaic 2009-12-23 01:11:31

+0

通過Apache的服務的ProxyPass nginx的靜態文件: 像: 的ProxyPass /媒體的http://本地主機:5000/ ProxyPassReverse /媒體的http://本地主機:5000/ – tsoporan 2009-12-23 01:22:38

+0

編輯:以上的評論被剝奪請參閱http:/ /dpaste.com/hold/136840/ – tsoporan 2009-12-23 01:24:54

回答

29

嗯,有點grepping代碼周圍表明,有可能是得到了沿途均勻更深的錯誤消息。

在Django /核心/文件/ storage.py,線210

(這是1.1.1),我們有:

def path(self, name): 
    try: 
     path = safe_join(self.location, name) 
    except ValueError: 
     raise SuspiciousOperation("Attempted access to '%s' denied." % name) 
    return smart_str(os.path.normpath(path)) 

所以錯誤必須要走出safe_join的()。

在django/utils/_os.py中,我們有以下內容。注意它拋出的倒數第三行ValueError異常:

===========================

def safe_join(base, *paths): 
    """ 
    Joins one or more path components to the base path component intelligently. 
    Returns a normalized, absolute version of the final path. 

    The final path must be located inside of the base path component (otherwise 
    a ValueError is raised). 
    """ 
    # We need to use normcase to ensure we don't false-negative on case 
    # insensitive operating systems (like Windows). 
    base = force_unicode(base) 
    paths = [force_unicode(p) for p in paths] 
    final_path = normcase(abspathu(join(base, *paths))) 
    base_path = normcase(abspathu(base)) 
    base_path_len = len(base_path) 
    # Ensure final_path starts with base_path and that the next character after 
    # the final path is os.sep (or nothing, in which case final_path must be 
    # equal to base_path). 
    if not final_path.startswith(base_path) \ 
     or final_path[base_path_len:base_path_len+1] not in ('', sep): 
     raise ValueError('the joined path is located outside of the base path' 
         ' component') 
    return final_path 

==================

嗯,「加入的路徑位於基本路徑組件的外部」。現在在那裏有幾個對abspathu()的調用(它定義在該例程的上方,對於NT而言與其他操作系統不同)。 abspathu()通過添加os.cwdu()(當前工作目錄)將所有非絕對路徑轉換爲絕對路徑。

問題:任何機會,你有任何符號鏈接(符號鏈接)到您的媒體目錄?換句話說,它不是項目目錄的直接子項?我不知道這是否是一個有效的問題,它只是從我的腦海中跳出來。

問題:什麼self.locationname被傳遞給safe_join()?

野驢猜:是self.location空?

另一個瘋狂的猜測:MEDIA_ROOT莫名其妙地變成/media/

如果你已經安裝了自己的Django副本(這並不難),試着在這些例程中添加一些打印語句,然後將其作爲開發服務器運行。打印輸出將轉到控制檯。

更新:嗯。你說「2)self.location和name的值是:/ home/tsoporan/site/media和/media/albums/anthem-for-the-underdog/30103635.jpg」

以下路徑任何意義?

"/home/tsoporan/site/media/media/albums/anthem-for-the-underdog" 

請注意.../media/media/...在那裏。

另外,這是什麼操作系統? Django rev?

+0

1)不,我沒有到我的媒體目錄的符號鏈接。 2)self.location和name的值是: /home/tsoporan/site/media和/media/albums/anthem-for-the-underdog/30103635.jpg - (這是一張專輯,但是問題與藝術家或專輯相​​同) 3)self.location不爲空。 4)我相信MEDIA_ROOT仍然是一樣的。 – tsoporan 2009-12-23 01:36:22

+0

請注意我上面的更新。在評論中格式化它會有點棘手。 – 2009-12-23 02:25:04

2

啊想出來,有點尷尬,但事實證明,錯誤是更高的。我用腳本來插入這些圖像,然後再次通過它,發現我的路徑以/ media /開頭。

現在我有大約4000個錯誤路徑的圖像......有沒有辦法以某種方式修改所有這些圖像的路徑?或者需要重新上傳?

謝謝大家,爲我的錯誤道歉。

+0

看到我的回答如下... – 2009-12-23 17:32:17

2

你真的應該就此問一個新問題。請嘗試以下操作:

寫一個獨立的Django的腳本,看起來像這樣:

from django.core.management import setup_environ 
from mysite import settings 
setup_environ(settings) 
from django.db import transaction 

from app.models import Album # or whatever your model name is 

for a in Album.objects.all(): 
    # Do something to cleanup the filename. 
    # NOTE! This will not move the files, just change the value in the field. 
    a.filename = re.sub(r'^/media', '', a.filename) 
    a.save() 

transaction.commit_unless_managed() # flush all changes 
56

我在upload_to定義中放置了一個前導斜槓時出現此錯誤。

BAD

pic = models.ImageField(upload_to="/uploads/product_images/") 

GOOD

pic = models.ImageField(upload_to="uploads/product_images/") 
+0

這是要走的路。文檔 - [upload_to](http://django.me/upload_to) – 2013-11-07 06:20:45

1

,如果你想使用其他位置,如/數據/圖像/ MYFILE /,你應該設置你的Django設置MEDIA_ROOT到/ data /圖片.py文件。

9

作爲別人的注意事項,當您在尋找靜態文件資源中有雙「//」時,可能會導致此問題。

{{ STATIC_URL }}/style.css # Causes the issue it should be 
{{ STATIC_URL }}style.css 
+0

您需要更多投票。這在我的設置中引起了問題。謝謝! – Javier 2014-04-18 03:04:14

+0

對我來說也是同樣的問題......有趣的是,這並沒有發生在'Nginx'或'manage.py runserver'背後。但是我已經有了額外的'/'好幾個月了,我只是在從'gunicorn'切換到'uwsgi'時才發現它,並且不得不在本地測試'uwsgi'。 – danidee 2017-09-01 13:32:10

+0

謝謝我的代表,正是我遇到的問題! – 2018-01-12 18:58:42

-1

我也有這個錯誤。通過調試我發現以下異常正在引發。

SuspiciousOperation(u"Attempted access to '2015-03-19-08:29:51-2-f8945842891244629dfd0c0af4c72a9c.pdf' denied.",) 

順便說一句,我使用的Django存儲器(V1.1.8)到S3(使用S3boto後端)存儲的媒體文件。我正在使用django 1.7.6。

但是,如果我切換到存儲文件名與出冒號(:)它似乎工作。我還沒有弄清楚什麼是根本原因。只要發佈這個,以防止這對其他人有幫助。顯然,django或django-storages不喜歡帶冒號的文件名。

0

我發現,通過使用愚蠢的print語句,某些媒體文件的/media前綴在它們的url路徑中。雖然默認存儲選項可處理該問題,但如果您使用django-storages中的S3BotoStorage,則會出現問題。

所以我固定它通過覆蓋_normalize_name(由@彼得 - 羅威爾在回答引導):

class MediaStorage(FixedUrlBotoStorage): 
    location = settings.MEDIAFILES_LOCATION 

    # Overriding function because some media files are stored with '/media' prefixed (which causes problems) 
    def _normalize_name(self, name): 
     if name.startswith('/media'): 
      name = name.lstrip('/media') 
     return super(MediaStorage, self)._normalize_name(name)