I have a list of tempfiles like this:
urls = [#<Tempfile:/tmp/down20190222-7434-18yoxw4.jpg>, #<Tempfile:/tmp/down20190222-7434-1r8c4y2.jpg>, #<Tempfile:/tmp/down20190222-7434-qpyiy1.JPG>, #<Tempfile:/tmp/down20190222-7434-q8xyup.mp4>]
now I want to zip these files for users to download it:
t = Tempfile.new('tmp-zip')
Zip::OutputStream.open(t.path) do |zos|
urls.each do |file|
zos.print IO.read(file)
end
end
send_file t.path, :type => "application/zip", :filename => "myfile.zip"
t.close
but I got the error closed stream excluded from capture: DSN not set
at the line: zos.print IO.read(file). What was I wrong in this case?
This is my full code:
if posts.present?
urls = []
posts.each do |post|
urls << post.filestack_image_url if post.filestack_image_url.present?
urls << post.photo_attributes('original')['url'] if post.photo.present?
urls << post.filestack_video_url if post.filestack_video_url.present?
urls << post.video_attributes('remote')['url'] if post.video.present?
end
urls = urls.collect {|url| download_url(url) }.compact
t = Tempfile.new('tmp-zip')
Zip::OutputStream.open(t.path) do |zos|
urls.each do |file|
zos.print IO.read(file.path.to_s.split("/")[-1])
end
end
send_file t.path, :type => "application/zip", :filename => "Awesome.zip"
t.close
end
Related
I implemented a show action to retrieve a pdf file url
namespace :api do
namespace :v2 do
get '/patients/:id', to: 'patients#show'
end
end
http://localhost:3005/api/v2/patients/1894
{
"id": 1894,
"name": "Test",
"file": {
"url": "https://some-url-com"
},
"student_id": 20998,
"created_at": "2019-07-02T13:27:10.975-04:00",
"updated_at": "2019-07-02T13:54:53.248-04:00",
....
....
}
If a user accesses the show link then it should just return pdf file. I am trying to open pdf from the show endpoint. I tried following methods in controller but not having luck
patient = Patient.find(params[:id])
open(patient.file.url).read
also tried send_file
send_data patient.file.url, :type => "application/pdf", :disposition => 'attachment'
but not having luck.
Is there any way I can have show url return pdf?
First, get the file:
require 'open-uri'
download = open('https://some-url-com')
IO.copy_stream(download, 'tmp/my_document.pdf')
Then send the file as part of your JSON:
pdf_filename = File.join(Rails.root, 'tmp/my_document.pdf')
# add this to your JSON where desired
send_file(pdf_filename, :filename => 'your_document.pdf', :type => 'application/pdf')
A simple way:
require "open-uri"
file = URI.open("https://some-url-com") # ruby 3+ must use URI.open
# it's a File (or Tempfile), you can do file things to it
# file # => #<File:/tmp/open-uri20220818-414775-wdh4sb>
# file.path # => /tmp/open-uri20220818-414775-wdh4sb
# file.read # => "%PDF-1.5\n%\xE4\xF0\xED\xF8\n8 ..."
send_data file.read, type: "application/pdf"
# or
send_file file.path, type: "application/pdf"
I'm trying to import users avatar from a CSV and attach to the users with ActiveStorage.
I've created a rake task for this, but it's not working (and do not throws any error). In my CSV there are only 2 fields: email and avatar (avatar is the url to the file, that is on another server).
This is the task:
require 'csv'
namespace :import do
desc "Import avatars to users from CSV"
task avatars: :environment do
filename = File.join Rails.root, "avatars.csv"
CSV.foreach(filename, headers: true, col_sep: ";", header_converters: :symbol) do |row|
User.find_by(email: row[:email]) do |u|
u.avatar.attach(URI.parse(row[:avatar]).open)
end
end
end
end
Any advice?
Thanks for your help.
Have you tried to catch the any exception and print the problem in the console?
Something like that:
require 'csv'
namespace :import do
desc "Import avatars to users from CSV"
task avatars: :environment do
begin
filename = File.join Rails.root, "avatars.csv"
CSV.foreach(filename, headers: true, col_sep: ";", header_converters: :symbol) do |row|
User.find_by(email: row[:email]) do |u|
u.avatar.attach(URI.parse(row[:avatar]).open)
end
end
rescue StandardError => e
logger = Logger.new(STDOUT)
logger.error e.message
logger.error e.backtrace.join("\n")
end
end
end
Also, are you sure you have users with that email?
I am new to Ruby on Rails .I am working on project where I need to send multiple Zip files To client.
I am using RubyZip for this .
def Download
unless params[:fileLists].nil?
file_name = "Peep-#{Time.now.to_formatted_s(:number)}.zip"
t = Tempfile.new("my-temp-filename-#{Time.now.to_formatted_s(:number)}")
Zip::OutputStream.open(t.path) do |z|
for _file in params[:fileLists]
unless _file.empty?
if File.file? _file
#z.add(File.basename(_file),_file)
z.put_next_entry(File.basename _file)
z.print IO.read(_file)
#send_file _file , disposition: 'attachment',status: '200'
end
end
end
end
#Sending Zip file
send_file t.path, :type => 'application/zip',
:disposition => 'attachment',
:filename => file_name
t.close
end
end
end
This is Working fine for all other file formats except Zip files .How it can be done ?
I resolved it by modifying my method .I used IO.binread(_file) instead of IO.read(_file) to read file.
Zip::OutputStream.open(t.path) do |z|
for _file in params[:fileLists]
unless _file.empty?
if File.file? _file
#z.add(File.basename(_file),_file)
z.put_next_entry(File.basename _file)
z.print IO.binread(_file)
end
end
end
end
#Sending Zip file
send_file t.path, :type => 'application/zip',
:disposition => 'attachment',
:filename => file_name
rubyzip is a lib for creating / working with zip archives in ruby.
ยป gem install rubyzip
Sample code
require 'zip/zip'
require 'zip/zipfilesystem'
def download_all
attachments = Upload.find(:all, :conditions => ["source_id = ?", params[:id]])
zip_file_path = "#{RAILS_ROOT}/uploads/download_all.zip"
# see if the file exists already, and if it does, delete it.
if File.file?(zip_file_path)
File.delete(zip_file_path)
end
# open or create the zip file
Zip::ZipFile.open(zip_file_path, Zip::ZipFile::CREATE) { |zipfile|
attachments.each do |attachment|
#document_file_name shd contain filename with extension(.jpg, .csv etc) and url is the path of the document.
zipfile.add( attachment.document_file_name, attachment.document.url)
end
}
#send the file as an attachment to the user.
send_file zip_file_path, :type => 'application/zip', :disposition => 'attachment', :filename => "download_all.zip"
end
I have a rake task and CSV files that I need to process; they are located in sub-directory of the lib\tasks directory:
\foo
one.csv
two.csv
...
foo.rake
The task:
task foo: :environment do
# for each file in directory
Dir.foreach("./*.csv") do |file| # not valid
# process CSV file's content
CSV.foreach(file, {:headers => true, :col_sep => ";"}) do |row|
...
end
end # Dir
end # task
How do I references files that are relative to the rake task?
I got to thinking about this more and I think combining File.join and Dir.glob will allow you to process all your csv files:
require "csv"
foo_dir = File.join(Rails.root, "lib", "tasks", "foo")
task foo: :environment do
# for each file in directory
Dir.glob(foo_dir + "/*.csv") do |csv_file|
# process CSV file's content
CSV.foreach(csv_file, {:headers => true, :col_sep => ";"}) do |row|
#...
end
end # Dir
end # task
EDIT: As #craig pointed out in the comment below, this can be accomplished more succinctly by using File.dirname and __FILE__:
require "csv"
task foo: :environment do
# for each file in directory
Dir.glob(File.dirname(__FILE__) + "/*.csv").each do |file|
# process CSV file's content
CSV.foreach(csv_file, {:headers => true, :col_sep => ";"}) do |row|
#...
end
end # Dir
end # task
I have a rails 2.3.5 app getting upgraded to Rails 3. I did every thing I am required to do for upgrading and when I start the rails server using
rails server
it gives me this
Please switch to Ruby 1.9's standard CSV library. It's FasterCSV plus
support for Ruby 1.9's m17n encoding engine.
I am using ruby-1.9.2-p0 and have fastercsv (1.5.3) gem installed. with the help of puts statements, i was able to track down where the error occurred. i found that the execution stops at this line
Bundler.require(:default, Rails.env) if defined?(Bundler)
in application.rb file. I tried many things but none worked .. please help..
Remove fasterCSV from your Gemfile in the application. Bundler is trying to require FasterCSV because you have it specified in the Gemfile.
with 1.9 you no longer need/can use the fastercsv gem, since it's bundled in the std lib.
Now you just need to do:
require 'csv'
CSV.open("temp.csv", "w") do |csv|
csv << ["line1row1", "line1row2"]
csv << ["line2row1", "line2row2"]
# ...
end
This is the solution i found:
require 'fastercsv'
require 'csv'
class ImportFileToAssetsWithFasterCsv < ActiveRecord::Migration
def self.up
if CSV.const_defined? :Reader
csv = FasterCSV
else
csv = CSV
end
file = 'db/staticfiles/DB-good-rightnames-forimport.csv'
csv.foreach(file) do |row|
Asset.create!(:country => row[0], :city => row[1], :latlong => row[2], :XX => row[3], :DEC => row[4], :point_name => row[5], :system_type => row[6], :system_brand => row[7], :function => row[8], :operator_name => row[9], :operator_brand => row[10], :parent_company => row[11], :app => "WWW", :language => "en", :source => "XXX", :Z_name => "International", :pref_format => "")
end
end
def self.down
IspcAsset.destroy_all()
end
end
Look here too http://www.wherethebitsroam.com/blogs/jeffw/fastercsv-csv-ruby-18-19-and-rails-30
If used FasterCsv in loop or in the code just change it with Csv and works for me.
Remove gem 'fastercsv' from gem file.
Just write your code in controller, no need add other code in somewhere in config.
This is the example of wrong code.
class HomeController < ApplicationController
require 'fastercsv'
def download_csv
#invitation = Invitation.find(params[:id])
#activities = Version.where("created_at >= ?", #invitation.created_at)
if params[:export]
csv_string = FasterCSV.generate do |csv|
# header row
csv << ["Date", "Event", "Details"]
#activities.each do |act|
csv << [act.created_at.strftime("%d-%m-%Y"), act.event, act.item_id]
end
end
timestamp = Time.now.strftime('%Y-%m-%d_%H:%M:%S')
send_data csv_string,
:type => 'text/csv; charset=iso-8859-1; header=present',
:disposition => "attachment; filename=goal_history_#{timestamp}.csv"
end
end
and just corrected with changing word FasterCsv to Csv and it works. like below
class HomeController < ApplicationController
require 'csv'
def download_csv
#invitation = Invitation.find(params[:id])
#activities = Version.where("created_at >= ?", #invitation.created_at)
if params[:export]
csv_string = CSV.generate do |csv|
# header row
csv << ["Date", "Event", "Details"]
#activities.each do |act|
csv << [act.created_at.strftime("%d-%m-%Y"), act.event, act.item_id]
end
end
timestamp = Time.now.strftime('%Y-%m-%d_%H:%M:%S')
send_data csv_string,
:type => 'text/csv; charset=iso-8859-1; header=present',
:disposition => "attachment; filename=goal_history_#{timestamp}.csv"
end
end