2009-12-23 12 views
26

He estado teniendo un problema al intentar eliminar imágenes cargadas.Operación sospechosa Django

El error es a lo largo de estas líneas:

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

Después de leer todo parece que el error se debe al hecho de que está en busca de la imagen en el lugar equivocado (nótese primera barra,/media/doesn 't existe en el sistema de archivos)

Mi MEDIA_ROOT y MEDIA_URL son:

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

Mis modelos upload_to parámetro se pasa esta función:

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

Mis preguntas son:

1) ¿Cómo puedo solucionar este problema para futuras subidas?

2) ¿Es posible arreglar las rutas de mis imágenes actuales sin tener que volver a cargarlas?

Saludos, Tito

+0

cómo están sirviendo archivos estáticos? ¿Qué url estás usando para los archivos estáticos? Sirviendo – czarchaic

+0

archivos estáticos con nginx a través de Apache ProxyPass: igual: ProxyPass/medios http: // localhost: 5000/ ProxyPassReverse/medios http: // localhost: 5000/ – tsoporan

+0

Editar: El comentario anterior fue despojado ver http://dpaste.com/hold/136840/ – tsoporan

Respuesta

29

Bueno, un poco grepping alrededor en el código de muestra que puede haber un mensaje de error más profundo que quedó homogeniza a lo largo del camino.

en django/core/archivos/storage.py, la línea 210 (esto es en 1.1.1) tenemos:

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

también lo ha hecho el error de estar saliendo de safe_join().

En django/utils/_os.py, tenemos lo siguiente. Tenga en cuenta el ValueError que arroja sobre la tercera a la última línea:

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

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 

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

Hmmm, "La ruta unida está ubicada fuera del componente de la ruta base". Ahora hay un par de llamadas a abspathu() allí (que se define justo arriba de esta rutina y es diferente para NT que para otros sistemas operativos). abspathu() convierte todas las rutas no absolutas en absolutas al hacer tachuelas en os.cwdu(), el directorio de trabajo actual.

Pregunta: ¿Por casualidad tiene un enlace simbólico (enlace simbólico) a su directorio multimedia? En otras palabras, ¿no es un hijo directo del directorio del proyecto? No sé si esta es una pregunta válida, simplemente salió de mi cabeza.

Pregunta: ¿Cuáles son los valores de self.location y name que se están pasando a safe_join()?

Salvaje-adivinanza: ¿es self.location vacío?

Otro asno salvaje: ¿MEDIA_ROOT de alguna manera se cambió a /media/?

Si tienes tu propia copia de Django instalada (no es difícil de hacer), intenta poner algunas instrucciones de impresión en estas rutinas y luego ejecútalas como servidor de desarrollo. La salida de impresión irá a la consola.

Actualización: Hmmm. Usted dijo "2) Los valores para self.location y name son:/home/tsoporan/site/media y /media/albums/anthem-for-the-underdog/30103635.jpg"

Hace la siguiente ruta de acceso ¿cualquier sentido?

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

Nota del .../media/media/... allí.

Además, ¿qué sistema operativo es este? Django rev?

+0

1) No, no tengo un enlace simbólico a mi directorio multimedia. 2) Los valores para self.location y name son: /home/tsoporan/site/media y /media/albums/anthem-for-the-underdog/30103635.jpg - (esto es para un álbum pero el el problema es el mismo para artistas o álbumes) 3) self.location no está vacío. 4) MEDIA_ROOT sigue siendo el mismo, creo. – tsoporan

+0

Tenga en cuenta mi actualización anterior. Hubiera sido un poco complicado formatearlo en un comentario. –

2

Ah lo averigué, un poco embarazoso, pero resulta que el error fue más arriba. Estaba conectando estas imágenes con un script y al volver a verlo me di cuenta de que mis rutas comenzaban con/media /.

Ahora tengo alrededor de 4000 imágenes con rutas equivocadas ... ¿hay alguna forma de modificar de algún modo las rutas para todas estas imágenes? ¿O será necesario volver a cargar?

Gracias a todos, me disculpo por mi error.

+0

Ver mi respuesta a continuación ... –

2

Realmente debería hacer una nueva pregunta sobre esto. Pruebe lo siguiente:

escribir un script django independiente que se ve algo como esto:

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

Recibí este error cuando puse una barra diagonal en la definición de upload_to.

BAD

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

BUENA

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

Este es el camino a seguir. Docs - [upload_to] (http://django.me/upload_to) –

1

si desea utilizar otro lugar, como por ejemplo/data/images/mi_archivo /, debe establecer que raíz_soporte a/datos/imágenes en los ajustes de Django archivo .py

9

Como nota para otros, este problema puede deberse a que tiene un doble '//' en el recurso de archivo estático que está buscando.

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

necesita más votos. esto estaba causando el problema en mi configuración. ¡Gracias! – Javier

+0

Mismo problema para mí .... Curiosamente, esto no sucedía en la producción detrás de 'Nginx' o con' manage.py runserver'. pero he tenido el '/' extra durante meses y solo lo descubrí cuando estaba tratando de cambiar de 'gunicorn' a' uwsgi' y tuve que probar 'uwsgi' localmente. – danidee

+0

¡Gracias por mi bien, exactamente el problema que tuve! –

-1

Recibí este error también. Al depurar descubrí que se está planteando la siguiente excepción.

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

Por cierto, estoy usando Django almacenamientos (v1.1.8) para almacenar mis archivos multimedia en S3 (usando S3boto back-end). Estoy usando django 1.7.6.

Pero si cambio a almacenar con nombre de archivo sin dos puntos (:) parece que funciona. Todavía no he descubierto cuál es la causa raíz. Solo publique esto en caso de que esto sea útil para otra persona. Aparentemente, django o django-storage no le gustan los nombres de archivo con dos puntos.

0

Descubrí, mediante el uso de declaraciones tontas print, que algunos archivos multimedia tienen /media con prefijo en sus rutas de URL. Si bien la opción de almacenamiento predeterminada maneja eso, hay un problema si usa S3BotoStorage desde django-storages.

Así me fijo reemplazando el _normalize_name (guiada por la respuesta por @ peter-rowell):

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)