My app cannot load some images from the server - ruby-on-rails

I'm using Ruby on Rails on my local WEBrick server.
I'm generating some images of websites from urls, writing them to my local filesystem, and displaying them. I name the images by their url but replace all \ with -. Some images seem to not be loading because it cannot find the images on my filesystem, and I get the broken image icon. However, I see that all the images are there when I check my filesystem.
This is the error I get in my logs:
Started GET "/images/image_site/http:--www.urbandictionary.com-define.php?term=slim%20shady.jpg?1309465379" for 127.0.0.1 at Thu Jun 30 13:23:06 -0700 2011
ActionController::RoutingError (No route matches "/images/image_site/http:--www.urbandictionary.com-define.php"):
This is my html code:
<img alt="Http:--www.urbandictionary.com-define.php?term=slim%20shady" class="site_image" src="/images/image_site/http:--www.urbandictionary.com-define.php?term=slim%20shady.jpg?1309465379">
What going on and how can I fix this? Please let me know if I need to provide more information.

Looks like you're not properly encoding your image names in the src attribute. I'd guess that you have a file with a name like this:
http:--www.urbandictionary.com-define.php?term=slim%20shady.jpg
But when you have this:
src="/images/image_site/http:--www.urbandictionary.com-define.php?term=slim%20shady.jpg?1309465379"
The filename looks like this:
/images/image_site/http:--www.urbandictionary.com-define.php
because everything after the first ? is considered to be part of the query string.
Replacing the slashes with hyphens is not good enough, you're still leaving all sorts of holes for confusion and nefarious intent. Instead, you should generate the image file names completely, something like id.jpg where id is the image's ID in your database. Then, store the original filename in your database and only show that filename (properly encoded!) to people, don't use it in your local file system.
A quick fix would be to properly URL encode your src attributes. But you really should fix up how you handle the images or you will leave yourself open to all sorts of trouble.

You need to place images in your public/ folder and then you can access them from there. By default Rails will server static assets primarily from public/.

Related

Rails DateTime re-format using #{DateTime.now}

I have a task in Rails that exports an xml, I've one line in it though
tmp_filename="#{Rails.root}/tmp/orders-#{o.id}-#{DateTime.now}.xml"
and this outputs the xml file with a filename like
orders-42-2015-01-28T17:22:35+00-00.xml
This is the way it shows up when its uploaded directly to amazon s3, the problem is I need to get rid of the colons and just have dashes because the system thats taking these files doesn't work properly with the colon in the filename.
The strange thing is that when I download the file from s3 it downloads as dashes.
I'm not sure how or if I can use strftime on #{}
Could anybody help with what I'm trying to do. Or if this is just an amazon s3 thing and the file is actually being generated with the - and not : already.
Strftime doesn't seem to work on amazon s3, the file still uploads as the original format even after adding
tmp_filename="#{Rails.root}/tmp/orders-#{o.id}-#{DateTime.now.strftime('%d-%m-%Y-%H%M%S')}.xml"
and it also adds an extra +00:00 at the end for some reason that I can't get rid of
Can't you just format the DateTime without colons, for example:
tmp_filename="#{Rails.root}/tmp/orders-#{o.id}-#{DateTime.now.strftime('%Y-%m-%d-%H-%M-%S')}.xml"
With this you'll get the time in format like below, without colons:
irb(main):010:0> DateTime.now.strftime('%Y-%m-%d-%H-%M-%S')
=> "2015-01-29-10-50-30"

Display PDF in iframe in RoR

I would like to display a pdf in an iframe in one of my Rails projects. My current code is <iframe src="tmp/data.pdf"></iframe>, but when I go to this page, I get the error: "No route matches [GET] /Users//development//tmp/data.pdf".
data.pdf is in this location, so I think I'm doing something wrong with my routes file, and maybe I have to route the file to a path appropriately. I've tried playing around with a few things, but haven't had much luck so far. Can anyone provide any help?
Rails only exposes the contents of the "public" subfolder to the webbrowser so no code/configuration can be downloaded by any user...
Try putting the file there and it should work.
UPDATE 1
Also you need to note, that the "public" part does not have to be included in the URL. So in your case the url would be just "/data.pdf".

How to download image from url and display in view

I am trying to download an image and displaying it in a view in rails.
The reason why I want to download it is because the url contains some api-keys which I am not very fond of giving away.
The solution I have tried thus far is the following:
#Model.rb file
def getUrlMethod
someUrlToAPNGfile = "whatever.png"
file = Tempfile.new(['imageprependname', '.png'], :encoding => "ascii-8bit")
file.write(open(data).read)
return "#{Rails.application.config.action_mailer.default_url_options[:host]}#{file.path}"
end
#This seems to be downloading the image just fine. However the url that is returned does not point to a legal place
Under development I get this URL for the picture: localhost:3000/var/folders/18/94qgts592sq_yq45fnthpzxh0000gn/T/imageprependname20130827-97433-10esqxh.png
That image link does not point anywhere useful.
My theories to what might be wrong is:
The tempfile is deleted before the user can request it
The url points to the wrong place
The url is not a legal route in the routes file
A am currently not aware of any way to fix either of these. Any help?
By the way: I do not need to store the picture after I have displayed it, as it will be changing constantly from the source.
I can think of two options:
First, embed the image directly in the HTML documents, see
http://www.techerator.com/2011/12/how-to-embed-images-directly-into-your-html/
http://webcodertools.com/imagetobase64converter
Second, in the HTML documents, write the image tag as usual:
<img src="/remote_images/show/whatever.png" alt="whatever" />
Then you create a RemoteImages controller to process the requests for images. In the action show, the images will be downloaded and returned with send_data.
You don't have to manage temporary files with both of these options.
You can save the file anywhere in the public folder of the rails application. The right path would be something like this #{Rails.root}/public/myimages/<image_name>.png and then you can refer to it with a URL like this http://localhost:3000/myimages/<image_name>.png. Hope this will help.

How to change filename prompt text browser Save As dialog?

In my web page (rendered by Rails), I'd like to let the user right-click on a photo to bring up the browser's Save As dialog, to let the user save the photo to their hard drive.
However, the photos on my server have unusual filenames (long hex names) with no file extension. The filename prompt in the Save As dialog has this ugly filename. If the user hits save, they'll end up with a poorly-named file, with no file extension.
The web page is aware of the photo's real file name (the name that came off the camera, for example). Is there a way for me to programmatically override the Save As dialog's filename prompt with a filename of my choosing?
I'm aware of the Content-Dispostion header, and that via this header a filename can be specified. However, I think that in order to be able to make use of this header, I need to load/render the entire file to the browser. If the asset to be made available for download is a movie, that loading of the file could timeout the browser...like, if it's a 100meg video.
Thoughts?
-A
I think I understand the problem here because I encountered (and resolved) at least part of it myself not too long ago.
I have some large mp3's and I link to them on my website
A few problems
I needed to set my content-disposition header to attachment in order to prevent files from automatically streaming whenever a user clicked the download button
my files are on a remote server
my files are large (100MB)
large files can tie up rails controllers if not handled properly
Now, Michael Koziarsky advises in this article that the best way to keep your rails processes free when serving large files, is to create a download action in your controller, and the do something like this (note the use of x_sendfile=>true):
def download
send_file '/path/to/podcast.mp3', :type => 'application/octet-stream', :disposition => 'attachment', :filename=>'something.mp3', :x_sendfile=>true
end
:x_sendfile tells apache to let the file through without tying up a rails controller process. The rest of the code sets the filename and the content-disposition header.
Great, but I'm on heroku, like everyone else nowadays. So I can't use x_sendfile.
I found that I couldn't modify the nginx configuration file either as it's locked down by heroku so it was not possible to get x-accel-redirect (nginx equivalent of x-sendfile) working
So, I decided to add a perl script (see below) to the cgi-bin on our asset-host and this script sets the content-disposition to attachment and gives our file a name too.
Instead of doing a restful download like this:
link_to "download", download_podcast_path(#podcast.mp3)
we just link to the mp3 making sure that we go in through the cgi-bin so that the perl script gets called on every mp3 that leaves the server
# I'm using haml
%a{:href=>"http://afmpodcast.com/cgi-bin/download.cgi?ID=#{#podcast.mp3}"}
download
The result is that my rails controller is no longer called into action when someone downloads a file
I found the perl script here and chopped it up a bit to work for me:
#!/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
My code, is on github but you'll likely have all sorts of problems using it on your machine as i make heavy use of ENV variables that I store in bashrc and I have no documentation or tests ^hides^
You could do some smart server side url rewrite, like for example rewriting foo.mpeg to youveryuglyfilenamewithoutextension.
Set the Content-Disposition to "attachment; filename="...that's fine. "attachment" explicitly means it's not to be rendered in the browser, file renaming works nonetheless (or possibly particularly for that case).
Based on your comments, you have a few problems.
You want to set the filename using your Rails app.
The file is on a remote host and your Rails app is acting as a middleman.
The file might be big, so you want the file to be sent out to the browser as you receive it instead of queuing the whole thing.
Streaming only with Rails is tricky for a few reasons.
You would need an HTTP client that lets you access the message body as you receive data instead of blocking until you have everything. Net::HTTP is not that client. I'm not sure what library would be better suited.
Once you have a more event-driven way to get your file in pieces, you can pass a proc to the render:
render :text => proc { |response, output| ... }
output can be used like an IO object. Some servers may buffer before sending anyway, though, so that's something to look out for.
It would be easier not handle the byte-shuffling in Rails.
If your webserver or the proxy in front of your webserver supports the X-REPROXY-URL HTTP header, your application can set that header and your webserver or proxy will stream the file.
Perlbal is the only proxy server I know of that supports that header out of the box.
An Apache2 module is also available.

jquery ajax load (full URL)

hi is there a wait to load a full url.?
url= 'http://www.example.com/whatever.php'
$('#selector').load(url); // this way returns null (empty result)
instead of :
url = 'whatever.php'
$('#selector').load(url); // works fine
Some may think whats the difference i want to use this because im using multiple directories. so i could be on a page like...
example.com/dir/
but the dir folder will not have the whatever.php
so anyone has a fix for this that i should always use the full url?
thank you.
You could always use relative paths
putting / before the path will tell the browser to go the root of the page. For your example you could call /whatever.php.
You can also move up one directory at a time. Lets say you are in a page at http://www.example.com/dir/foo/bar.php and want to access something in the dir folder, you could specify ../inTheDir.php to move up one directory or ../../inTheRoot.php to move up two.
This should work for you, but based on your comment it sounds like you have a problem somewhere else since your www. page doesn't seem to respond correctly.
No, there isn't.
If http://www.example.com/ takes longer to load than http://example.com/ then it is probably because you have the DNS record for example.com cached but not the record for www.example.com.
Corrected after having realized a typo changed the meaning of the question.:
This is a case of having a mismatch between the host name the page is loaded from and the host name the Ajaxed resource is requested from. i.e. The Same Origin Policy.
Pick a host name to be canonical, use that one in your requests, and redirect (with a 301 status code) from the other so that people don't go to the wrong one by mistake.

Resources