Web2py:下载文件/显示图像 [英] Web2py: downloading files / displaying images

查看:127
本文介绍了Web2py:下载文件/显示图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近跳进了Web2py框架,我觉得很好。但是,我现在陷入了一个基本问题。



上下文



建筑是科学代码的界面:人们填写表格并提交。然后,数据(写入共享文件夹中的文件)由代码处理,在后台运行作为守护程序(该代码与该网站没有链接,除了此共享文件夹以及<$ c $之间的JSONRPC链接C>代码 - >网站)。
代码生成我想向网站用户提供的文件和图像(即返回他们要求的结果)。
当作业完成后,代码使用JSONRPC服务链接将结果推送到网站,该链接工作完美。结果是一个文件夹,其生成名称基本上具有以下结构:

  unique_folder_name / 
file1.txt
file2.csv
file3.xls
image1.png
image2.png



当前的实现(不能正常工作)



目前我有3个DB:

 #作业数据库
db.define_table(job,
Field('owner','string',length = 60,required = True,writable = True ,可读= True),
Field('uniq_id',string,length = 60,required = True,unique = True,writable = False,可读= True))

#结果数据库
db.define_table(result,
Field(job,reference job),
Field(x,integer,default = 1),
字段(y,整数,默认= 0),
字段(z,整数,默认= 0),
字段(数据 ,length = 500),
Field(message,string,length = 200))

#文件数据库
db.define_table(file,
Field(job,reference job),
字段(file,upload),
Field(isimage,boolean,default = False))

推送结果,Web2py中的一些模块在result数据库中创建条目,并在与作业相关联的files数据库中创建条目。
由于我没有找到方法使文件(已经在文件系统上)可用于Web2py,而不复制到上传文件夹,所以我目前存储的文件(在模块中):

  stream = open(os.path.join(directory,_file),'rb')
current.db.file.insert(job = jid,file = current.db.file.file.store(stream,_file),isimage = isimg)

然后,当我想创建一个视图与图像,我做(在一个模块):

  rows = current.db((current.db.file.job == jid)&(current.db.file.isimage == True))。select()
表示行中的行:
div。 append(I(_src = URL(c =default,f =download,args = os.path.join(directory,row.file)),_width =500,_height =500))

在视图中:`{{div}}``



问题



这只是不工作...显示页面的源代码如下:

 < i height =500src =/ mycode / default /下载// path / to / directory / file.file.9b7d3a0367de0843.6d732d72732e706e67.pngwidth =500>< / i> 

如果我在地址栏中输入这个URL,文件正确下载,否则图像不会显示在网页上。
此外,我必须给出文件的路径,即使Web2py将文件复制到'upload'文件夹(使用其新的安全丑名):),否则链接不起作用。
所以:没有图像显示,加上文件被复制到'upload'文件夹:(



我迷路了,没有看到如何解决这个问题(我也试图在构建图像URL时添加请求对象,并且还尝试了一个自定义下载功能...没有工作到目前为止)。



编辑(解决方案)



嗯,我错过的代码中有一个明显的错误:images tag helper不是,但 IMG :)由于与twitter引导程序中使用的 I 标记混淆导致的简单错误...因此解决了显示问题。
对于流式传输文件,无需在上传文件夹中复制它们(即不使用数据库中的上传字段), rochacbruno 感谢他)让我走上正轨。

解决方案

所以这里是我问题的完整解决方案。
$ b

db.py 文件中,我通过此定义替换了文件表(所以文件保留在它们的位置,不复制到web2py上传文件夹):

 #文件数据库
db.define_table(file,
Field(job,reference job),
Field(name,string,length = 30,required = True),#存储文件名(不含路径)
Field(isimage,boolean,default = False))

然后,在控制器例如'mycontroller'),我已经将这个函数定义为流文件:

  from mymodule import OUTPUT#这是基数文件目录
from gluon.contenttype import contenttype

def export():
#允许下载文件
jid = request.args(0)
fid = request.args(1)

如果没有(jid,fid):
res ='无效的URL'
else:
#获取文件行
row = db.file(fid)

#一些检查(如果你知道你在做什么,则不需要)
jrow = db.job(jid)
如果行为None:
res =unknown文件ID
elif jrow.id为无:
res =未知作业ID
其他:
filename = row.name
#jrow.perma_id,是jobDB中的一个字段,我用来创建一个唯一的
#目录名,所以作业IDjid的文件位于: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'] ='附件; filename =%s'%filename
res = response.stream(open(fullname,rb),chunk_size = 4096)

return res

请注意,我在此时遇到另一个问题:我首先想到将完整路径作为请求参数传递(例如 URL(c ='mycontroller',f ='export',args =(路径,文件名))),
但它没有工作,因为路径包含被分解为多个参数的'/'...
如果您没有像我这样简单的路径(即只需一个组件更改),则可以存储例如,进入文件DB的路径。



然后,对于视图(使用模块或任何您喜欢的):

  rows = current.db((current.db.file.job == jid)&(current.db.file.isimage == True))。 select()
行中的行:
div.append(IMG(_src = URL(c =mycontroller,f =export,args =(jid,fid),_width =500 ,_height =500))

注意在帮助标签已被正确的 IMG 替换。 'jid'是作业ID,'fid'是要显示/下载的文件ID。


I've recently jumped into Web2py framework which I find very good. However, I'm now stuck with a 'basic' problem.

Context

The website I'm building is an interface for scientific code: people fills-in a form and submit it. The data (written in a file inside a shared folder) is then being processed by the code, running as a daemon in the background (the code has no link with the website, excepts this shared folder and a JSONRPC link between code->website). The code generates files and images that I would like to make available to the website users (ie. returning them back the results they asked for). When a job is finished, the code 'push' the results to the website using a JSONRPC service link, which works perfectly. The results are in a folder with a generated name which have basically the following structure:

unique_folder_name/
        file1.txt
        file2.csv
        file3.xls
        image1.png
        image2.png

The current implementation (not working properly)

Currently I have 3 DBs:

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

When the code 'push' the results, some modules in Web2py create the entry in the 'result' db, and entries in the 'files' db associated to the job. Since I did not find a way to make files (already on the filesystem) available to Web2py without it copying to the upload folder, I currently store the files like that (in a module):

stream = open(os.path.join(directory, _file), 'rb')
current.db.file.insert(job=jid, file=current.db.file.file.store(stream, _file), isimage=isimg)

Then, when I want to create a view with the images, I do (in a module):

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

and in the view: `{{=div}}``

Problems

This is just not working... The source code of the displayed page is like:

<i height="500" src="/mycode/default/download//path/to/directory/file.file.9b7d3a0367de0843.6d732d72732e706e67.png" width="500"></i>

If I type this URL in the address bar, the file download properly, but otherwise the image is not displayed on the webpage. Also, I have to give the path of the file, even if Web2py did copy the file into 'upload' folder (with its new safe ugly name:)), otherwise the link is just not working. So: no image displayed, plus the files are copied into 'upload' folder anyway :(

I'm lost, and dont see how to fix this. (I've tried also to add the request object when building the image URL, and also tried a custom download function... none worked so far).

EDIT (SOLUTION)

Well, there is an obvious bug in my code that I've missed: images tag helper is not I, but IMG :) Simple mistake arising from the confusion with the I tag used in twitter bootstrap for icons... So that solves the display issue. For streaming files without copying them in the upload folder (ie. not using an upload field in the DB), rochacbruno (many thanks to him) has put me on the right track. See my own answer for the complete solution.

解决方案

So here is the complete solution to my problem.

In the db.py file, I've replaced the 'file' table by this definition (so files stay where they are, and are not copied into the web2py upload folder):

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

Then, in a controller (eg. 'mycontroller'), I've defined this function to stream files:

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

Please note, that I ran into another problem at this point: I first thought to pass the full path as a request argument (eg. URL(c='mycontroller', f='export', args=(path, filename))), but it did not work since path was containing '/' that were split into as many arguments... If you don't have an easy path like me (ie. just one component change), you can store the path into the 'file' DB for instance.

Then, for the view (using either a module or whatever you like):

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

Notice that the I helper tag has been replaced by the correct IMG one. 'jid' is the job ID, and 'fid' is the file ID you want to display/download.

这篇关于Web2py:下载文件/显示图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆