我最近跳进了Web2py框架,我觉得非常好。但是,我现在遇到了“基本”问题。
我正在建立的网站是科学代码的界面:人们填写表格并提交。然后,代码处理数据(写在共享文件夹内的文件中),在后台作为守护进程运行(代码没有与网站的链接,除了此共享文件夹和{{1}之间的JSONRPC链接})。 代码生成我希望网站用户可以使用的文件和图像(即将它们返回给他们要求的结果)。 作业完成后,代码会使用JSONRPC服务链接将结果“推送”到网站,该链接完美运行。结果位于具有生成名称的文件夹中,该文件夹基本上具有以下结构:
code->website
目前我有3个数据库:
unique_folder_name/
file1.txt
file2.csv
file3.xls
image1.png
image2.png
当代码“推送”结果时,Web2py中的某些模块会在“结果”数据库中创建条目,并在“文件”数据库中创建与作业关联的条目。 由于我没有找到一种方法来使文件(已经在文件系统上)可用于Web2py而不将其复制到上传文件夹,我当前存储这样的文件(在模块中):
# Job database
db.define_table("job",
Field('owner', 'string', length=60, required=True, writable=True, readable=True),
Field('uniq_id', "string", length=60, required=True, unique=True, writable=False, readable=True))
# Result database
db.define_table("result",
Field("job", "reference job"),
Field("x", "integer", default=1),
Field("y", "integer", default=0),
Field("z", "integer", default=0),
Field("data", "string", length=500),
Field("message", "string", length=200))
# File database
db.define_table("file",
Field("job", "reference job"),
Field("file", "upload"),
Field("isimage", "boolean", default=False))
然后,当我想用图像创建视图时,我(在一个模块中):
stream = open(os.path.join(directory, _file), 'rb')
current.db.file.insert(job=jid, file=current.db.file.file.store(stream, _file), isimage=isimg)
并在视图中:`{{= div}}``
这只是不起作用......显示页面的源代码如下:
rows = current.db((current.db.file.job==jid) & (current.db.file.isimage==True)).select()
for row in rows:
div.append(I(_src=URL(c="default", f="download", args=os.path.join(directory, row.file)), _width="500", _height="500"))
如果我在地址栏中输入此URL,则文件正确下载,否则图像不会显示在网页上。 此外,我必须给出文件的路径,即使Web2py确实将文件复制到'upload'文件夹(带有新的安全丑陋名称:)),否则链接无法正常工作。 所以:没有显示图像,加上文件被复制到'upload'文件夹中:(
我迷路了,不知道如何解决这个问题。 (我还尝试在构建图像URL时添加请求对象,并尝试了自定义下载功能......到目前为止还没有工作)。
嗯,我的代码中有一个明显的错误,我错过了:图片标记帮助器不是<i height="500" src="/mycode/default/download//path/to/directory/file.file.9b7d3a0367de0843.6d732d72732e706e67.png" width="500"></i>
,而是I
:)与{{1}混淆引起的简单错误在twitter bootstrap中用于图标的标签...这样就解决了显示问题。
对于流媒体文件而不在上传文件夹中复制它们(即不使用数据库中的IMG
字段), rochacbruno (非常感谢他)让我走上正轨。请参阅我自己的答案以获得完整的解决方案。
答案 0 :(得分:2)
您必须创建自己的下载功能
import os
def my_download():
base_path = request.args(0) # /path
subdirectory = request.args(1) # directory
filename = request.args(2)
fullpath = os.path.join(request.folder, base_path, subdirectory, filename)
response.stream(os.path.join(request.folder, fullpath))
默认/下载旨在与db和默认存储方式一起使用。
答案 1 :(得分:2)
所以这是我问题的完整解决方案。
在db.py
文件中,我已按此定义替换了'file'表(因此文件保留原样,不会复制到web2py上传文件夹中):
# File database
db.define_table("file",
Field("job", "reference job"),
Field("name", "string", length=30, required=True), # stores the filename (without path)
Field("isimage", "boolean", default=False))
然后,在一个控制器(例如'mycontroller')中,我已经定义了这个函数来传输文件:
from mymodule import OUTPUT # this is the base directory of the files
from gluon.contenttype import contenttype
def export():
# allow to download files
jid = request.args(0)
fid = request.args(1)
if None in (jid, fid):
res = 'Invalid URL'
else:
# get the file row
row = db.file(fid)
# some checks (not necessary if you know what you're doing)
jrow = db.job(jid)
if row is None:
res = "unknown file ID"
elif jrow.id is None:
res = "unknown job ID"
else:
filename = row.name
# jrow.perma_id, is a field in the 'job' DB, that I use to create a unique
# directory name, so the files of job ID 'jid' are under: OUTPUT/perma_id/
fullname = os.path.join(OUTPUT, jrow.perma_id, filename)
ext = os.path.splitext(filename)[1]
response.headers['Content-Type'] = contenttype(ext)
response.headers['Content-disposition'] = 'attachment; filename=%s' % filename
res = response.stream(open(fullname, "rb"), chunk_size=4096)
return res
请注意,此时我遇到了另一个问题:我首先想到将完整路径作为请求参数传递(例如。URL(c='mycontroller', f='export', args=(path, filename))
),
但它没有用,因为path
包含'/'被分成多个参数......
如果您没有像我这样的简单路径(即只更改一个组件),您可以将路径存储到“文件”DB中。
然后,对于视图(使用模块或任何你喜欢的):
rows = current.db((current.db.file.job==jid) & (current.db.file.isimage==True)).select()
for row in rows:
div.append(IMG(_src=URL(c="mycontroller", f="export", args=(jid, fid), _width="500", _height="500"))
请注意,I
帮助程序标记已被正确的IMG
替换。 'jid'是作业ID,'fid'是您要显示/下载的文件ID。
答案 2 :(得分:0)
从Web2Py视图下载
从Web2Py书中: 链接到静态文件夹中的音频或视频文件时,如果要强制浏览器下载文件而不是通过媒体播放器流式传输音频/视频,请在URL上添加“附件”。这告诉web2py将HTTP响应的Content-Disposition标头设置为“附件”。例如:
<a href="/app/static/my_audio_file.mp3?attachment">Download</a>
单击上面的链接时,浏览器将提示用户下载MP3文件,而不是立即流音频。
我已经成功地将以上内容用于json和csv文件。 请注意,以上内容不适用于 private 文件夹中的文件。
从Web2Py控制器下载
def my_download():
directory = '2e6d2ba1-52d7-4927-b91d-c7568b25314d'
Cat = 'foobar'
path=os.path.join(request.folder,'static', directory + Cat + '.json')
return response.stream(open(path,'rb'), attachment=True, filename=Cat)