Add image from URL to Excel with Axlsx - ruby

I'm using the (Axlsx gem and it's working great, but I need to add an image to a cell.
I know it can be done with an image file (see Adding image to Excel file generated by Axlsx.?), but I'm having a lot of trouble using our images stored in S3 (through Carrierwave).
Things I've tried:
# image.url = 'http://.../test.jpg'
ws.add_image(:image_src => image.url,:noSelect => true, :noMove => true) do |image|
# ArgumentError: File does not exist
or
ws.add_image(:image_src => image,:noSelect => true, :noMove => true) do |image|
# Invalid Data #<Object ...>
Not sure how to proceed

Try using read to pull the contents into a tempfile and use that location:
t = Tempfile.new('my_image')
t.binmode
t.write image.read
t.close
ws.add_image(:image_src => t.path, ...

To add an alternative answer for Paperclip & S3 as I couldn't find a reference for that besides this answer.
I'm using Rails 5.0.2 and Paperclip 4.3.1.
With image URLs like: http://s3.amazonaws.com/prod/accounts/logos/000/000/001/original/logo.jpg?87879987987987
#logo = #account.company_logo
if #logo.present?
#logo_image = Tempfile.new(['', ".#{#logo.url.split('.').last.split('?').first}"])
#logo_image.binmode # note that our tempfile must be in binary mode
#logo_image.write open(#logo.url).read
#logo_image.rewind
end
In the .xlsx file
sheet.add_image(image_src: #logo_image.path, noSelect: true, noMove: true, hyperlink: "#") do |image|...
Reference link: http://mensfeld.pl/tag/tempfile/ for more reading.
The .split('.').last.split('?').first is to get .jpg from logo.jpg? 87879987987987.

Related

wkhtmltopdf, 0.12.6, Warning: Blocked access to file

When upgrade wkhtmltopdf to 0.12.6, it came to such messages and the image did not show in the target pdf:
Warning: Blocked access to file /path/to/bpa_product_layering.png
BTW, the same source html file works well with 0.12.5
This is caused by the change of default behavior in version 0.12.6 of wkhtmltopdf. wkhtmltopdf disables local file access by default now. It could be solved by adding the command line parameter
--enable-local-file-access
or the combination
--disable-local-file-access --allow <path>
For those that are using laravel-snappy, add the 'enable-local-file-access' option in the config\snappy.php:
'pdf' => [
'enabled' => true,
'binary' => env('WKHTML_PDF_BINARY', '/usr/local/bin/wkhtmltopdf'),
'timeout' => false,
'options' => [
'enable-local-file-access' => true,
'orientation' => 'landscape',
'encoding' => 'UTF-8'
],
'env' => [],
],
'image' => [
'enabled' => true,
'binary' => env('WKHTML_IMG_BINARY', '/usr/local/bin/wkhtmltoimage'),
'timeout' => false,
'options' => [
'enable-local-file-access' => true,
'orientation' => 'landscape',
'encoding' => 'UTF-8'
],
'env' => [],
],
wkhtmltopdf disables local file access by default in the 0.12.6 version
Just bumping this thread with a correction in case you're still getting the same error in spite of using:
--enable-local-file-access
For some reason, this cmd line argument does not work when being specified after input/output files, you have to write this argument right after wkhtmltopdf.exe.
So
wkhtmltopdf.exe --enable-local-file-access input.html output.pdf
instead of other variants.
in my case, I put "enable-local-file-access": "", in options, it worked.
In Windows with Python, I came across a similar error as well when running code:
result = imgkit.from_file('postlayout.A.html', 'out.jpg', config=wkhtmltoimage_binaries)
Error:
Warning: Blocked access to file C:/XXXXXX/background.A.jpg
Error: Failed to load about:blank, with network status code 301 and
http status code 0 - Protocol "about" is unknown
What I did to resolve this:
Add variable options
kitoptions = {
"enable-local-file-access": None
}
Add options to call
FROM
result = imgkit.from_file('postlayout.A.html', 'out.jpg', config=wkhtmltoimage_binaries)
TO
result = imgkit.from_file('postlayout.A.html', 'out.jpg', config=wkhtmltoimage_binaries, options=kitoptions)
Full Source:
import imgkit
#library path to kit
path_wkthmltopdf = r'C:\Program Files\wkhtmltopdf\bin\wkhtmltoimage.exe'
wkhtmltoimage_binaries = imgkit.config(wkhtmltoimage=path_wkthmltopdf)
#OPTIONS
kitoptions = {
"enable-local-file-access": None
}
html_file_directory = r'C:\XXXX\template'
result = imgkit.from_file('postlayout.A.html', 'out.jpg', config=wkhtmltoimage_binaries, options=kitoptions)
if result:
print("successful")
else:
print("failed")
For the C API, contrary to what the documentation says, it's not load.blockLocalFileAccess but loadPage.blockLocalFileAccess that you must set to "false":
wkhtmltoimage_set_global_setting(settings, "loadPage.blockLocalFileAccess", "false");
Hopefully, the documentation will be updated soon; see issue #4763.
I confirm that the problem comes from the wkhtmltopdf version. For those on Symfony (3.4), just add an option in config.yml:
knp_snappy:
pdf:
options:
enable-local-file-access: true
I know am a bit late in party but just wanted to write clear example with c# here so one can understand clearly.
ProcessStartInfo proc = new ProcessStartInfo();
proc = new ProcessStartInfo();
proc.RedirectStandardError = true;
proc.UseShellExecute = false;
proc.WorkingDirectory = #"" + Config.WkhtmltopdfPath;
proc.FileName = #"" + Config.WkhtmltopdfPath + #"\wkhtmltopdf.exe";
proc.Arguments = #" --enable-local-file-access -T 0 -B 0 --page-width 210mm --page-height 450mm " + fileName + ".html " + fileName + ".pdf";
Process inkscape = Process.Start(proc);

File.new command for Ruby to upload mp3 file to soundcloud

I'm now trying to upload a mp3 file to Soundcloud. Here I'm bogged down to the use of File.new command in Ruby.
I send a request and a passing parameter looks like the below.
Parameters: {..."mp3_1"=>#<ActionDispatch::Http::UploadedFile:0x007ff24d5e3ea8 #tempfile=#<Tempfile:/var/folders/kk/y_wprlln2qv6mzylj03g14x00000gn/T/RackMultipart20160316-21426-14vu8x1.mp3>, #original_filename="datasecurity.mp3", #content_type="audio/mp3", #headers="Content-Disposition: form-data; name=\"mp3_1\"; filename=\"datasecurity.mp3\"\r\nContent-Type: audio/mp3\r\n">}
Then, I write File.new command with the potentail file name and params[:mp3_1] like the below.
client = Soundcloud.new(:access_token => 'XXX')
track = client.post('/tracks', :track => {
:title => 'This is my sound',
:asset_data => File.new("file name",params[:mp3_1])
})
Now I get an error saying:
no implicit conversion of ActionDispatch::Http::UploadedFile into String
The paperclip function works ( storing file to the storage directly has been what I've done ) but this file.new doesn't allow me to move forward. If I can get any help, I really appreciate that (:
Best
you already have a file, no need to create a new one with File.new
have a closer look to your dump :
#tempfile=#<Tempfile:/var/folders/...../RackMultipart20160316-21426-14vu8x1.mp3
this is a file, you may use it directly in your call
client.post('/tracks', :track => {
:title => 'This is my sound',
:asset_data => params[:mp3_1].tempfile)
})

Add CSS minifier to Sprockets

I have a web application which uses rack.
The code:
set :assets, (Sprockets::Environment.new { |env|
env.js_compressor = Uglifier.new({
:output => {
:preserve_line => true,
:bracketize => true,
:beautify => true,
:indent_level => 4,
:semicolons => true,
},
:mangle => false
})
env.append_path(APP_ROOT + "/app/assets/images")
env.append_path(APP_ROOT + "/app/assets/javascripts")
env.append_path(APP_ROOT + "/app/assets/stylesheets")
})
I now want to add a CSS minifier to it.
Can someone explain why only javascript files are taken into the JS compressor above?
Can I add something like env.css_compressor = YUI::CssCompressor.new() after the JS_compressor to get my requirement done
UPDATE: Well the second actually worked. But I have no clue how it worked :)
You hadn't set up the Sprockets::Environment.css_compressor variable, so there was no compressor available to run on text/css assets.
puts Sprockets::Environment.methods.inspect
#=> [...#css_compressor, #css_compressor=, #js_compressor, #js_compressor=,...]
To answer your question about how assets are loaded, yes the default is to point to one load path and you can as well manipulate that to include others.
https://github.com/sstephenson/sprockets
The load path is an ordered list of directories that Sprockets uses to
search for assets. To add a directory to your environment's load path, use the append_path and prepend_path methods.

Can I have a File-instance with content without saving the file?

For paperclip I have a file that I add programmatically. The file is a generated PDF. So basically I don't need this file to be saved to my server's HDD. What I do now is the following:
#tempfile = Tempfile.open( ['','.pdf'], nil, 'wb', encoding: "ASCII-8BIT") do |file|
file << render_to_string( pdf: "pdf_file.pdf", layout: "pdf", template: "projects/generatePDF" )
end
#export.pdf = File.open( #tempfile.path ) # Paperclip Attachment
These are three steps: Create, write, open. So I'm wondering if we can do this easier, something like the following would be great:
#export.pdf = File.new( render_to_string( pdf: "pdf_file.pdf", layout: "pdf", template: "projects/generatePDF" ) )
Try using a stringio - this is a subclass of IO that is backed by a string rather than a file.

problems retrieving file extension in CI

How can I retrieve the file extension of an image while uploading?
I don't have any problems with the upload, just retrieving the files extension , which would be useful when creating thumbnails dynamically.
Thanks
http://codeigniter.com/user_guide/libraries/file_uploading.html
$this->upload->data()
This is a helper function that returns an array containing all of the data related to the file you uploaded. Here is the array prototype:
Array
(
[file_name] => mypic.jpg
[file_type] => image/jpeg
[file_path] => /path/to/your/upload/
[full_path] => /path/to/your/upload/jpg.jpg
[raw_name] => mypic
[orig_name] => mypic.jpg
[client_name] => mypic.jpg
[file_ext] => .jpg
[file_size] => 22.2
[is_image] => 1
[image_width] => 800
[image_height] => 600
[image_type] => jpeg
[image_size_str] => width="800" height="200"
)
So after the user has uploaded something, you probably want to store the file extension in your database along with other details about the image :-)
$name_of_file_with_extn = $this->upload->data('file_name')
you can change the item name from the below list
file_name Name of the file that was uploaded, including the filename extension
file_type File MIME type identifier
file_path Absolute server path to the file
full_path Absolute server path, including the file name
raw_name File name, without the extension
orig_name Original file name. This is only useful if you use the encrypted name option.
client_name File name as supplied by the client user agent, prior to any file name preparation or incrementing
file_ext Filename extension, period included
file_size File size in kilobytes
is_image Whether the file is an image or not. 1 = image. 0 = not.
image_width Image width
image_height Image height
image_type Image type (usually the file name extension without the period)
image_size_str A string containing the width and height (useful to put into an image tag)
This might help you.
After you uploaded the file, you can get its property by:
$saved_file_name = $this->upload->data('file_name');
// will give you the filename along with the extension
If you want to get only the file extension before uploading it, use core PHP:
$file_ext = pathinfo($_FILES["file"]["name"], PATHINFO_EXTENSION);
or to make it clean
$filename= $_FILES["file"]["name"];
$file_ext = pathinfo($filename,PATHINFO_EXTENSION);

Resources