【问题标题】:How to change filename prompt text browser Save As dialog?如何更改文件名提示文本浏览器另存为对话框?
【发布时间】:2011-04-01 20:05:03
【问题描述】:

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

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

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

我知道 Content-Dispostion 标头,并且可以通过此标头指定文件名。但是,我认为为了能够使用此标头,我需要将整个文件加载/渲染到浏览器。如果可供下载的资产是电影,则文件的加载可能会使浏览器超时……例如,如果它是 100 兆视频。

想法?

-A

【问题讨论】:

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


    【解决方案1】:

    我想我理解这里的问题,因为不久前我自己遇到(并解决了)至少部分问题。

    我有一些大的mp3's,我在我的website 上链接到它们

    几个问题

    • 我需要将我的 content-disposition 标头设置为 attachment 以防止文件在用户单击下载按钮时自动流式传输
    • 我的文件在远程服务器上
    • 我的文件很大 (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 变量并且我没有文档或测试 ^hides^

    【讨论】:

      【解决方案2】:

      您可以进行一些智能的服务器端 url 重写,例如将 foo.mpeg 重写为 youveryuglyfilenamewithoutextension

      【讨论】:

        【解决方案3】:

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

        【讨论】:

        • 嗨。 (先说要下载的文件在 Rails 服务器以外的服务器上。)在我的 Rails 控制器中,我可以设置 Content-Disposition 标头,但是如何在控制器中指定要下载的文件的 URL下载。目前,我正在使用 r = Net::HTTP.get_response() @content = r.body render :layout => false ...在我看来我渲染 并且我确实得到了保存作为提示...但仅在文件完全加载后。对于视频文件,这需要很长时间。但也许我不需要实际加载文件?想法?
        • 好吧,抱歉,这是一个特定于 Rails 的问题,我不能说太多。我相应地重新标记了您的问题,以吸引更多的 Rails 专家。通常,您只发送标头,然后开始发送要传输的文件的二进制数据。不知道您所描述的是否会导致这种行为,似乎并非如此。
        【解决方案4】:

        根据您的 cmets,您有一些问题。

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

        仅使用 Rails 进行流式传输很棘手,原因有几个。

        您将需要一个 HTTP 客户端,它允许您在接收数据时访问消息正文,而不是在获得所有内容之前进行阻塞。 Net::HTTP 不是那个客户端。我不确定哪个库更适合。

        一旦你有一个更加事件驱动的方式来获取你的文件,你可以将一个 proc 传递给渲染: render :text =&gt; proc { |response, output| ... }

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


        在 Rails 中不处理字节洗牌会更容易。

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

        Perlbal 是我所知道的唯一支持该标头的代理服务器。

        一个 Apache2 模块是also available

        【讨论】:

          猜你喜欢
          • 2013-02-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-22
          • 1970-01-01
          • 1970-01-01
          • 2010-10-18
          • 1970-01-01
          相关资源
          最近更新 更多