Nếu bạn chỉ cần đổi tên tệp, điều này sẽ phá vỡ cơ chế tải xuống. Hơn nữa, đôi khi bạn có thể muốn lưu tệp dưới một tên khác với tên gốc.Giả sử bạn có mô hình sau:
db.define_table("files",
Field("name", unique=True),
Field("file", "upload"))
Bạn cần phải mở rộng lĩnh vực tải lên với cửa hàng tùy chỉnh và lấy chức năng:
Field("file", "upload", custom_store=store_file, custom_retrieve=retrieve_file)
Các chức năng đơn giản là đang viết/đọc một tập tin từ một thư mục upload cố định :
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'))
Bây giờ trong bộ điều khiển, bạn cần sửa đổi form.vars trước khi chèn/cập nhật cơ sở dữ liệu và đặt tên tệp. Nếu bạn muốn giữ tên gốc của tệp được tải lên, điều này là không cần thiết.
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
Bạn cũng cần phải xác định một chức năng để tải về các tập tin như xây dựng trong response.download sẽ không làm việc:
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)
Để kết nối các dấu chấm, bạn cần xây dựng biểu mẫu. Trong ví dụ dưới đây tôi đang sử dụng cơ chế lưới mới tốt hơn các dạng cũ của trường (nhưng chưa được ghi trong sách).
upload = lambda filename: URL("download", args=[filename])
def index():
grid = SQLFORM.grid(db.files, onvalidation=validate, upload=upload)
return {"grid":grid}
Nếu bạn không muốn tất cả các fanciness của lưới điện, các mã điều khiển tương đương là:
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}
với request.vars.name_of_file.filename tôi nhận được tên tập tin ban đầu, nhưng làm thế nào để đổi tên đã tải lên. tôi nên làm gì với os.rename? Tôi đang tải lên các tệp zip khác nhau, vì vậy chúng cần phải là name_of_file.zip THANK YOU – Yebach
Bạn cũng có thể bỏ qua 'form.accepts' và xử lý tệp lưu. Tuy nhiên, đừng làm điều này với các tệp do người dùng tải lên vì bạn sẽ mở các cuộc tấn công traversal thư mục. – Anthony
cách đặt không mã hóa tệp bằng web2py. Vấn đề là tôi muốn các tập tin được tải lên được lưu trữ trong một thư mục với tên tập tin ban đầu, cos tôi có một kịch bản sau đó để xử lý nó và tên tập tin là quan trọng để xử lý tập tin ?? – Yebach