我有自定义下载功能。当用户点击下载图标时,第一个文件被解密然后下载。此下载图标存在于加载组件中。
如果解密成功,则返回文件。如果解密失败,我想显示“下载失败'。
”的Flash消息这是我的自定义下载功能:
def custom_download():
download_row = db(db.documents.id == request.args(0)).select().first()
download_file = download_row.file
# Name of file is table_name.field.XXXXX.ext, so retrieve original file name
org_file_name = db.documents.file.retrieve(download_file)[0]
file_header = "attachment; filename=" + org_file_name
response.headers['ContentType'] = "application/octet-stream"
response.headers['Content-Disposition'] = file_header
file_full_path = os.path.join(request.folder, 'uploads', download_file)
decrypted_file = decrypt_file(file_full_path)
if decrypted_file:
fh = open(decrypted_file, 'rb')
return response.stream(fh)
else:
return "Download Failed"
如何从控制器中触发Flash消息?或任何其他方式告诉用户下载失败。
答案 0 :(得分:1)
我能想到的最简单的方法是对文件执行ajax请求,如果结果是“下载失败”。然后你改变DOM以在页面上的某个容器中显示错误消息。您也可以让操作生成HTTP错误代码,这样您就不必解析返回的数据。
有一个你想要的例子:Download a file by jQuery.Ajax
$.fileDownload('some/file.pdf')
.done(function () { alert('File download a success!'); })
.fail(function () { alert('File download failed!'); });
答案 1 :(得分:1)
问题是如果下载链接是常规链接(即,不触发Ajax请求),那么如果您返回文件以外的其他内容,则会重新加载整个页面。或者,如果您使链接触发Ajax请求,您将无法返回文件。因此,一种方法是在解密失败的情况下重定向回原始页面:
if decrypted_file:
fh = open(decrypted_file, 'rb')
return response.stream(fh)
else:
session.flash = 'Download failed'
redirect(URL('original_controller', 'original_function', extension=False))
使用 session.flash
是因为存在重定向。另请注意,extension=False
可确保当前请求的扩展名不会传播到重定向URL(默认情况下,URL()
帮助程序会传播当前请求的扩展名。)
唯一的缺点是,如果出现故障,必须完全重新加载父页面,但假设失败的情况相对较少,这应该影响很小。
另一种方法是创建一个函数来生成解密文件并返回成功/失败消息,以及第二个函数来提供文件。您将向第一个函数发出Ajax请求,并根据结果显示失败消息或将window.location
设置为第二个函数的URL以下载文件。在成功下载的情况下,第一种方法更简单,效率更高(只有一个请求而不是两个)。