Commit 6475a4d3a3bef0a553b844b13068b077e78f3146

Authored by Braulio Bhavamitra
Committed by Rodrigo Souto
1 parent bb031599

Force a browser to save file as after clicking a uploaded file link

(ActionItem2829)
app/controllers/public/content_viewer_controller.rb
@@ -53,8 +53,9 @@ class ContentViewerController < ApplicationController @@ -53,8 +53,9 @@ class ContentViewerController < ApplicationController
53 # At this point the page will be showed 53 # At this point the page will be showed
54 @page.hit 54 @page.hit
55 55
56 - unless @page.mime_type == 'text/html' || (@page.image? && params[:view]) 56 + if @page.download? params[:view]
57 headers['Content-Type'] = @page.mime_type 57 headers['Content-Type'] = @page.mime_type
  58 + headers.merge! @page.download_headers
58 data = @page.data 59 data = @page.data
59 60
60 # TODO test the condition 61 # TODO test the condition
@@ -70,7 +71,7 @@ class ContentViewerController < ApplicationController @@ -70,7 +71,7 @@ class ContentViewerController < ApplicationController
70 71
71 #FIXME see a better way to do this. It's not need to pass this variable anymore 72 #FIXME see a better way to do this. It's not need to pass this variable anymore
72 @comment = Comment.new 73 @comment = Comment.new
73 - 74 +
74 if @page.has_posts? 75 if @page.has_posts?
75 posts = if params[:year] and params[:month] 76 posts = if params[:year] and params[:month]
76 filter_date = DateTime.parse("#{params[:year]}-#{params[:month]}-01") 77 filter_date = DateTime.parse("#{params[:year]}-#{params[:month]}-01")
app/models/article.rb
@@ -188,7 +188,7 @@ class Article < ActiveRecord::Base @@ -188,7 +188,7 @@ class Article < ActiveRecord::Base
188 pending_categorizations.clear 188 pending_categorizations.clear
189 end 189 end
190 190
191 - acts_as_taggable 191 + acts_as_taggable
192 N_('Tag list') 192 N_('Tag list')
193 193
194 acts_as_filesystem 194 acts_as_filesystem
@@ -268,7 +268,7 @@ class Article < ActiveRecord::Base @@ -268,7 +268,7 @@ class Article < ActiveRecord::Base
268 end 268 end
269 269
270 # returns the data of the article. Must be overriden in each subclass to 270 # returns the data of the article. Must be overriden in each subclass to
271 - # provide the correct content for the article. 271 + # provide the correct content for the article.
272 def data 272 def data
273 body 273 body
274 end 274 end
@@ -360,6 +360,16 @@ class Article < ActiveRecord::Base @@ -360,6 +360,16 @@ class Article < ActiveRecord::Base
360 false 360 false
361 end 361 end
362 362
  363 + def download? view = nil
  364 + (self.uploaded_file? and not self.image?) or
  365 + (self.image? and view.blank?) or
  366 + (not self.uploaded_file? and self.mime_type != 'text/html')
  367 + end
  368 +
  369 + def download_headers
  370 + {}
  371 + end
  372 +
363 named_scope :native_translations, :conditions => { :translation_of_id => nil } 373 named_scope :native_translations, :conditions => { :translation_of_id => nil }
364 374
365 def translatable? 375 def translatable?
app/models/uploaded_file.rb
@@ -86,6 +86,12 @@ class UploadedFile < Article @@ -86,6 +86,12 @@ class UploadedFile < Article
86 self.name = self.filename 86 self.name = self.filename
87 end 87 end
88 88
  89 + def download_headers
  90 + {
  91 + 'Content-Disposition' => "attachment; filename=\"#{self.filename}\"",
  92 + }
  93 + end
  94 +
89 def data 95 def data
90 File.read(self.full_filename) 96 File.read(self.full_filename)
91 end 97 end
test/fixtures/files/500.html 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +../../../public/500.html
0 \ No newline at end of file 2 \ No newline at end of file
test/functional/content_viewer_controller_test.rb
@@ -64,7 +64,19 @@ class ContentViewerControllerTest < ActionController::TestCase @@ -64,7 +64,19 @@ class ContentViewerControllerTest < ActionController::TestCase
64 assert_response :missing 64 assert_response :missing
65 end 65 end
66 66
67 - should 'produce a download-like when article is not text/html' do 67 + should 'produce a download-link when article is a uploaded file' do
  68 + profile = create_user('someone').person
  69 + html = UploadedFile.create! :uploaded_data => fixture_file_upload('/files/500.html', 'text/html'), :profile => profile
  70 + html.save!
  71 +
  72 + get :view_page, :profile => 'someone', :page => [ '500.html' ]
  73 +
  74 + assert_response :success
  75 + assert_match /^text\/html/, @response.headers['Content-Type']
  76 + assert @response.headers['Content-Disposition'].present?
  77 + end
  78 +
  79 + should 'produce a download-link when article is not text/html' do
68 80
69 # for example, RSS feeds 81 # for example, RSS feeds
70 profile = create_user('someone').person 82 profile = create_user('someone').person
@@ -1254,7 +1266,7 @@ class ContentViewerControllerTest < ActionController::TestCase @@ -1254,7 +1266,7 @@ class ContentViewerControllerTest < ActionController::TestCase
1254 1266
1255 get 'view_page', :profile => profile.identifier, :page => article.path.split('/') 1267 get 'view_page', :profile => profile.identifier, :page => article.path.split('/')
1256 assert_tag :tag => 'a', :attributes => { :href => "/#{profile.identifier}/#{article.path}?comment_page=2", :rel => 'next' } 1268 assert_tag :tag => 'a', :attributes => { :href => "/#{profile.identifier}/#{article.path}?comment_page=2", :rel => 'next' }
1257 - end 1269 + end
1258 1270
1259 should 'not escape acceptable HTML in list of blog posts' do 1271 should 'not escape acceptable HTML in list of blog posts' do
1260 login_as('testinguser') 1272 login_as('testinguser')