如何更改文件名提示文本浏览器另存为对话框?

时间:2010-08-20 19:13:35

标签: ruby-on-rails browser content-disposition

在我的网页(由Rails呈现)中,我想让用户右键单击照片以显示浏览器的“另存为”对话框,让用户将照片保存到硬盘中。

但是,我服务器上的照片有不寻常的文件名(长十六进制名称),没有文件扩展名。 “另存为”对话框中的文件名提示具有此丑陋的文件名。如果用户点击保存,他们最终会得到一个命名不佳的文件,没有文件扩展名。

网页 知道照片的真实文件名(例如,从相机中取出的名称)。有没有办法让我以编程方式使用我选择的文件名覆盖“另存为”对话框的文件名提示符?

我知道 Content-Dispostion 标头,并且可以通过此标头指定文件名。但是,我认为为了能够使用这个头,我需要将整个文件加载/渲染到浏览器。如果要下载的资源是电影,那么加载文件可能会使浏览器超时......就像是100meg视频一样。

思想?

-A

5 个答案:

答案 0 :(得分:1)

我想我在这里理解这个问题是因为我不久前遇到过(并且已经解决了)至少部分问题。

我有一些大的mp3's,我在website

上链接到它们

一些问题

  • 我需要将内容处置标题设置为附件,以防止文件在用户点击下载按钮时自动流式传输
  • 我的文件在远程服务器上
  • 我的文件很大(100MB)
  • 如果处理不当,大文件可以占用rails控制器

现在,Michael Koziarsky在this article中建议,在提供大型文件时保持rails进程免费的最佳方法是在控制器中创建下载操作,并执行类似这样的操作(注意使用的 x_sendfile =>真):

  def download
    send_file '/path/to/podcast.mp3', :type => 'application/octet-stream', :disposition => 'attachment', :filename=>'something.mp3', :x_sendfile=>true
  end

:x_sendfile 告诉apache让文件通过而不会占用rails控制器进程。其余代码设置文件名和内容处置标题。

很好,但我现在在heroku 就像现在的其他人一样。所以我不能使用x_sendfile。

我发现我无法修改nginx配置文件,因为它已被heroku锁定,因此无法获得 x-accel-redirect (nginx相当于 x-发送文件)工作

所以,我决定在我们的资产主机上的cgi-bin中添加一个perl script(见下文),这个脚本将内容处理设置为附件并提供我们的文件一个名字。

而不是像这样做一个安静的下载:

link_to "download", download_podcast_path(@podcast.mp3)

我们只是链接到mp3,确保我们通过cgi-bin进入,以便在每个离开服务器的mp3上调用perl脚本

# I'm using haml
%a{:href=>"http://afmpodcast.com/cgi-bin/download.cgi?ID=#{@podcast.mp3}"}
  download

结果是当有人下载​​文件时,我的rails控制器不再被激活

我找到了perl脚本here并将其切碎了一段时间为我工作:

#!/usr/local/bin/perl -wT

use CGI ':standard';
use CGI::Carp qw(fatalsToBrowser);

my $files_location;
my $ID;
my @fileholder;

$files_location = "../";

$ID = param('ID');

open(DLFILE, "<$files_location/$ID") || Error('open', 'file');
@fileholder = <DLFILE>;
close (DLFILE) || Error ('close', 'file');

print "Content-Type:application/x-download\n";
print "Content-Disposition:attachment;filename=$ID\n\n";
print @fileholder

我的代码在github,但你可能会在你的机器上使用它时遇到各种各样的问题,因为我大量使用我存储在bashrc中的ENV变量而且我没有文档或测试^隐藏^

答案 1 :(得分:0)

您可以执行一些智能服务器端网址重写,例如将foo.mpeg重写为youveryuglyfilenamewithoutextension

答案 2 :(得分:0)

将Content-Disposition设置为“attachment; filename =”......没关系。 “附件”明确表示不在浏览器中呈现,文件重命名仍然有效(或者可能特别适用于该情况)。

答案 3 :(得分:0)

为什么首先这个丑陋的文件名?如果我们知道原因,也许我们可以提出更好的解决方法。

如果无法更改该名称,我建议您在显示下载提示之前动态重写。

答案 4 :(得分:0)

根据您的评论,您遇到了一些问题。

  1. 您想使用Rails应用程序设置文件名。
  2. 该文件位于远程主机上,您的Rails应用程序充当中间人。
  3. 文件可能很大,因此您希望在收到文件时将文件发送到浏览器,而不是将整个文件排队。
  4. 由于某些原因,只使用Rails流是很棘手的。

    您需要一个HTTP客户端,它允许您在接收数据时访问邮件正文,而不是阻塞,直到您拥有所有内容。 Net :: HTTP不是那个客户端。我不确定哪个库更适合。

    一旦你有了一个更加以事件为导向的方式将你的文件分成几部分,你就可以将一个proc传递给渲染: render :text => proc { |response, output| ... }

    output可以像IO对象一样使用。不过,有些服务器可能会在发送之前进行缓冲,因此需要注意这一点。


    在Rails中处理字节重排更容易。

    如果您的网络服务器或您的网络服务器前的代理支持X-REPROXY-URL HTTP标头,您的应用程序可以设置该标头,您的网络服务器或代理将流式传输该文件。

    Perlbal是我所知道的唯一支持开箱即用标头的代理服务器。

    Apache2模块是also available