duda imagefield filefield descarga de archivo subidos previamentte

627 views
Skip to first unread message

refreegrata

unread,
Jul 7, 2010, 12:50:17 PM7/7/10
to Django-es
Hola lista. Yo otra vez con mis dudas de novato.

Yo uso Django 1.2.1 con Apache.

Primero que todo. Ya se subir archivos(carpeta con permisos, y la
configuracion de settings)

Mi duda es la siguiente. De que manera puedo en mis sitios colocar un
link para que los usuarios descarguen los archivos que previamente
subieron?

Primero debo aclarar que me gustaría que los usuarios sólo pudieran
tener acceso a los archivos a través del sitio, para que así no puedan
directamente colocar en la url algo como "misitio/archivo/
archivo1.pdf". Es por esto que en el archivo de configuracion de
Apache no he configurado el acceso al directorio, y es esta la razón
de que sólo pueda subir, pero no bajar los archivos.

Hay alguna manera de resolver esta situación que no implique dejar
libre el acceso a cualquiera, o configurar un .htaccess en donde cada
vez deban loguearse aparte del login inicial en el sitio, y sin usar
algún script en el servidor, para que fuera del sistema haga en un
comienzo una copia del archivo en cuestión a un directorio público
para después borrarlo?.

Disculpen si mi pregunta es demasiado simple.

Saludos.

P.D.: Para los otros archivos necesarios(CSS,js, etc.) no hay
problema, puesto que he guardado los archivos en el mismo directorio
del sitio, configure apache, y me manejo a través de rutas relativas,
por lo que no dependo de la configuración del MEDIA_ROOT y el
MEDIA_URL.

Andres Vargas - zodman

unread,
Jul 7, 2010, 12:59:49 PM7/7/10
to djan...@googlegroups.com
Lo que podrias hacer es django lea el archivo misitio/archivo/
archivo1.pdf lo guarde en un StringIO y se lo devuelva al cliente como
un httpResponse(blahblah, mimetype="application/pdf")

Otra es que el archivo misitio/archivo/
archivo1.pdf lo copies a otro dir misitio/archivo_publicos/
archivo1_<uniqueid>.pdf le digas al apache que no muestre listado de archivos
el uniqueid podria ser un hash de fecha y hora + nombre de archivo
para que nunca te de el mismo hash y un cron que cada 10 min borre los
archivos publicos ....

hay varias formas

2010/7/7 refreegrata <refre...@yahoo.com>:

> --
> Ha recibido este mensaje porque está suscrito a Grupo "Grupo de Usuarios del Framework Django de habla hispana" de Grupos de Google.
>  Si quieres publicar en este grupo, envía un mensaje de correo
> electrónico a djan...@googlegroups.com
>  Para anular la suscripción a este grupo, envíe un mensaje a django-es-...@googlegroups.com
>  Para obtener más opciones, visita este grupo en http://groups.google.com.bo/group/django-es.

--
Andres Vargas
www.zodman.com.mx

Rolando Espinoza La Fuente

unread,
Jul 7, 2010, 1:24:58 PM7/7/10
to djan...@googlegroups.com
2010/7/7 refreegrata <refre...@yahoo.com>:
[...]

> Primero debo aclarar que me gustaría que los usuarios sólo pudieran
> tener acceso a los archivos a través del sitio, para que así no puedan
> directamente colocar en la url algo como "misitio/archivo/
> archivo1.pdf". Es por esto que en el archivo de configuracion de
> Apache no he configurado el acceso al directorio, y es esta la razón
> de que sólo pueda subir, pero no bajar los archivos.

Una opción -como ya te respondieron- es cargar el contenido del archivo
y pasarlo al HttpResponse dentro un view.

No tendrías problema si los archivos son pequeños, si son muy grandes
entonces tendrías un consumo extra de memoria, y además si tienes
slow-clients podrías tener todo un proceso python/django mandando
un file de 100Mb que demoraría bastante.

Otra opción es usar soporte en el servidor para mandar el archivo,
es decir, tu le indicas al servidor web qué archivo mandar, y no es
tu aplicación quien envía el archivo.

En el caso de apache necesitas mod_xsendfile:

response = HttpResponse()
response['X-Sendfile'] = '/full/path/to/file'
response['Content-Type'] = 'some/content_type'
response['Content-Length'] = os.stat('/full/path/to/file').st_size
response['Content-Disposition'] = 'attachment; filename="foo"'
return response

En el caso de nginx se usa el header X-Accel-Redirect
http://wiki.nginx.org/NginxXSendfile

Pero esto te limitaría a un único servidor web que soportaría el enviar
archivos en tu aplicación. Tampoco podrías usar el dev server.

~Rolando

refreegrata

unread,
Jul 7, 2010, 2:06:48 PM7/7/10
to Django-es
ok. Claro, si la opción del HttpResponse y la de copiar los archivos a
un directorio temporal pudiesen generar un consumo de memoria muy
alto, la verdad es que estaría ante un problema, ya que los archivos
igual pueden ser relativamente pesados, combinado con un equipo de no
muy altos recursos. Y además lo de configurar cron para eliminar los
archivos antiguos, mmm, no se.¿que pasá si el cliente tiene una lenta
conexión de internet con un archivo relativamente grande, no podría
ser que estuviera eliminando archivos en descarga?

no se que haré.
Lo de usar xsendfile no lo conocía, pero mi problema , más que definir
"que enviar", es más bien controlar el "cuando enviar". Es decir, yo
estaría satisfecho si mi aplicación bloquea el acceso al directorio de
los archivos a cada usuario, a menos que este se hubiera logueado en
el sistema. Es decir, si realiza un login en la página principal,
puede acceder(ya sea a través de sistema , o directamente) a un
archivo, y una vez muera su variable de sessionel acceso es nuevamente
bloqueado. No se, alguna extraña manera de mezclar una variable de
sesión de django con un htpasswd o algo así.

Saludos.


On 7 jul, 13:24, Rolando Espinoza La Fuente <dark...@gmail.com> wrote:
> 2010/7/7 refreegrata <refreegr...@yahoo.com>:
> [...]
>
> > Primero debo aclarar que me gustaría que los usuarios sólo pudieran
> > tener acceso a los archivos a través del sitio, para que así no puedan
> > directamente colocar en la url algo como "misitio/archivo/
> > archivo1.pdf". Es por esto que en el archivo de configuracion de
> > Apache no he configurado el acceso al directorio, y es esta la razón
> > de que sólo pueda subir, pero no bajar los archivos.
>
> Una opción -como ya te respondieron- es cargar el contenido del archivo
> y pasarlo al HttpResponse dentro un view.
>
> No tendrías problema si los archivos son pequeños, si son muy grandes
> entonces tendrías un consumo extra de memoria, y además si tienes
> slow-clients podrías tener todo un proceso python/django mandando
> un file de 100Mb que demoraría bastante.
>
> Otra opción es usar soporte en el servidor para mandar el archivo,
> es decir, tu le indicas al servidor web qué archivo mandar, y no es
> tu aplicación quien envía el archivo.
>
> En el caso de apache necesitas mod_xsendfile:
>
> response = HttpResponse()
> response['X-Sendfile'] = '/full/path/to/file'
> response['Content-Type'] = 'some/content_type'
> response['Content-Length'] = os.stat('/full/path/to/file').st_size
> response['Content-Disposition'] = 'attachment; filename="foo"'
> return response
>
> En el caso de nginx se usa el header X-Accel-Redirecthttp://wiki.nginx.org/NginxXSendfile

refreegrata

unread,
Jul 7, 2010, 2:34:28 PM7/7/10
to Django-es
A propósito. En cuanto al consumo de memoria, que es más eficiente. El
Httpresponse o el copiar a una carpeta publica, y después eliminar.
Supongo que dependerá del archivo, contexto, etc. Pero en términos
generales?

La opción del stringio y el httpresponse aunque en teoría la entiendo,
la verdad es que aún no capto del todo como programarla. Yo vengo del
mundo PHP, y ahí yo hago algo como

header ('Content-Disposition:
attachment; filename='.$name);
header ("Content-Type: application/
octet-stream");
header ("Content-Length:
".filesize($rute));
readfile($rute);
die();

supongo que la idea aquí es algo similar.

Rolando Espinoza La Fuente

unread,
Jul 8, 2010, 12:43:23 PM7/8/10
to djan...@googlegroups.com
2010/7/7 refreegrata <refre...@yahoo.com>:

> A propósito. En cuanto al consumo de memoria, que es más eficiente. El
> Httpresponse o el copiar a una carpeta publica, y después eliminar.
> Supongo que dependerá del archivo, contexto, etc. Pero en términos
> generales?

Para copiar puedes usar shutil.copy(), aunque creo -si no usas windows-
te sería suficiente un enlace simbólico -> os.symlink()

> La opción del stringio y el httpresponse aunque en teoría la entiendo,
> la verdad es que aún no capto del todo como programarla. Yo vengo del
> mundo PHP, y ahí yo hago algo como
>
>                                header ('Content-Disposition:
> attachment; filename='.$name);
>                                header ("Content-Type: application/
> octet-stream");
>                                header ("Content-Length:
> ".filesize($rute));
>                                readfile($rute);
>                                die();

def view_passwd(request):
content = open('/etc/passwd').read()
response = HttpResponse(content, mimetype='application/octet-stream')
response['Content-Disposition'] = 'attachment; filename=passwd'
response['Content-Length'] = len(content)
return response

La opción del StringIO -creo- se utiliza cuando generas un pdf o imagén
on-the-fly. En apis donde escribes a un archivo, en lugar de:

something.save(open('foo', 'w'))
content = open('foo').read()

Utilizas un StringIO

buffer = StringIO()
something.save(buffer)
content = buffer.read()

Y te evitas escribir a disco.

~Rolando

Reply all
Reply to author
Forward
0 new messages