Si simplemente cambia el nombre del archivo, se romperá el mecanismo de descarga. Además, a veces es posible que desee guardar el archivo con un nombre diferente al original.Supongamos que usted tiene el siguiente modelo:
db.define_table("files",
Field("name", unique=True),
Field("file", "upload"))
necesita extender el campo de carga con la tienda personalizada y recuperar funciones:
Field("file", "upload", custom_store=store_file, custom_retrieve=retrieve_file)
Las funciones son simplemente escribir/leer un archivo de un directorio de carga fija :
import os
import shutil
def store_file(file, filename=None, path=None):
path = "applications/app_name/uploads"
if not os.path.exists(path):
os.makedirs(path)
pathfilename = os.path.join(path, filename)
dest_file = open(pathfilename, 'wb')
try:
shutil.copyfileobj(file, dest_file)
finally:
dest_file.close()
return filename
def retrieve_file(filename, path=None):
path = "applications/app_name/uploads"
return (filename, open(os.path.join(path, filename), 'rb'))
Ahora en el controlador que tenga que modificar el form.vars antes de la inserción de la base de datos/actualización se realiza y establecer el nombre del archivo. Si desea mantener el nombre original del archivo cargado, esto no es necesario.
def validate(form):
# set the uploaded file name equal to a name given in the form
if form.vars.file is not None:
form.vars.file.filename = form.vars.name
También es necesario definir una función para descargar el archivo como la estructura en response.download no funcionará:
import contenttype as c
def download():
if not request.args:
raise HTTP(404)
name = request.args[-1]
field = db["files"]["file"]
try:
(filename, file) = field.retrieve(name)
except IOError:
raise HTTP(404)
response.headers["Content-Type"] = c.contenttype(name)
response.headers["Content-Disposition"] = "attachment; filename=%s" % name
stream = response.stream(file, chunk_size=64*1024, request=request)
raise HTTP(200, stream, **response.headers)
para conectar los puntos, que necesita para construir el formulario. En el siguiente ejemplo, estoy usando el nuevo mecanismo de cuadrícula, que es mucho mejor que los formularios de la vieja escuela (pero aún no está documentado en el libro).
upload = lambda filename: URL("download", args=[filename])
def index():
grid = SQLFORM.grid(db.files, onvalidation=validate, upload=upload)
return {"grid":grid}
Si no quiere que todo el fanciness de la red, el código del controlador equivalente es:
def index():
if len(request.args):
form=SQLFORM(db.files, request.args[0], upload=URL("download"))
else:
form=SQLFORM(db.files, upload=URL("download"))
if form.process(onvalidation=validate).accepted:
response.flash = "files updated"
return {"form":form}
con request.vars.name_of_file.filename me sale el nombre del archivo original, pero la forma de renombrar el cargado ¿Debo hacerlo con os.rename? Estoy cargando diferentes archivos zip, por lo que necesitan ser name_of_file.zip GRACIAS – Yebach
También puede omitir 'form.accepts' y manejar el archivo, y se guarda. No hagas esto con los archivos subidos por el usuario, ya que estarás abierto a ataques cruzados de directorio. – Anthony
cómo configurar la codificación de archivos por web2py. Lo que quiero es que el archivo cargado se almacene en una carpeta con el nombre original del archivo, porque tengo otro script para procesarlo y el nombre del archivo es importante para el procesamiento de archivos. – Yebach