简体   繁体   中英

Downloading files in Mojolicious

Simple question. I have a .doc file generated in my mojolicious app. I want to download it. That's my question, how do I get the browser to download it?

I'm using the CPAN module MsOffice::Word::HTML::Writer to generate the doc.

Here is the sub routine in my mojolicious app, it is called by an Ajax request in Jquery:

sub down_doc {
  my $self = shift;

  my $doc = MsOffice::Word::HTML::Writer->new(
    title => "My new Doc",
    WordDocument => {View => 'Print'},
  );

  $doc->write("Content and Stuff");

  my $save = $doc->save_as("/docs/file.doc");

  $self->res->headers->content_disposition("attachment;filename=file.doc");
  $self->res->headers->content_type('application/msword');

  $self->render(data => $doc->content);
}

Here is my Ajax request in Jquery:

var request = $.ajax({
  url: "/down_doc",
  type: "post",
  data: {'data': data},
});

request.done(function(response, textStatus, jqXHR) {
  window.location.href = response;
});

I know that my Ajax "done" handler is wrong, I was just experimenting. How do I make my webpage prompt to save and download the .doc file?

You where pretty close, but I would recommend either of the following options...

File Download Processing with Mojolicious

You can install the plugin Mojolicious::Plugin::RenderFile to make this easy.

Example

plugin 'RenderFile';

sub down_doc {
  my $self = shift;

  my $doc = MsOffice::Word::HTML::Writer->new(
    title => "My new Doc",
    WordDocument => {View => 'Print'},
  );

  $doc->write("Content and Stuff");
  my $save = $doc->save_as("/docs/file.doc");    
  $self->render_file('filepath' => "/docs/file.doc");
}

Or if you want to only use Mojo the following will work, and is explained further at the link below.

use Cwd;
app->static->paths->[0] = getcwd;

sub down_doc {
  my $self = shift;

  my $doc = MsOffice::Word::HTML::Writer->new(
    title => "My new Doc",
    WordDocument => {View => 'Print'},
  );

  $doc->write("Content and Stuff");
  my $save = $doc->save_as("/docs/file.doc");    
  shift->render_static("/docs/file.doc");
}

Reference

This really isn't a problem on the server side, but rather that you can't save the response from an ajax request without using the (relatively new) File API. I would suggest replacing the ajax with a temporary form:

$('<form method="post" action="/down_doc">') 
    .append( 
       $('<input type="hidden" name="data">')
          .attr("value", JSON.stringify(data))
    )
    .appendTo('body') 
    .submit();

When form is submitted and your /down_doc handler replies with the appropriate content-disposition header and the document data, the browser will do the work of handling the file save.

If you're not planning to use the file on the server after the request, this line can be removed:

my $save = $doc->save_as("/docs/file.doc");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM