Pretty file size in Ruby?
How about the Filesize gem ? It seems to be able to convert from bytes (and other formats) into pretty printed values:
example:
Filesize.from("12502343 B").pretty # => "11.92 MiB"
http://rubygems.org/gems/filesize
Getting accurate file size in megabytes?
Try:
compressed_file_size = File.size("Compressed/#{project}.tar.bz2").to_f / 2**20
formatted_file_size = '%.2f' % compressed_file_size
One-liner:
compressed_file_size = '%.2f' % (File.size("Compressed/#{project}.tar.bz2").to_f / 2**20)
or:
compressed_file_size = (File.size("Compressed/#{project}.tar.bz2").to_f / 2**20).round(2)
Further information on %
-operator of String:
http://ruby-doc.org/core-1.9/classes/String.html#M000207
BTW: I prefer "MiB" instead of "MB" if I use base2 calculations (see: http://en.wikipedia.org/wiki/Mebibyte)
Convert human readable file size to bytes in ruby
There's filesize (rubygems)
It's quite trivial to write your own:
module ToBytes
def to_bytes
md = match(/^(?<num>\d+)\s?(?<unit>\w+)?$/)
md[:num].to_i *
case md[:unit]
when 'KB'
1024
when 'MB'
1024**2
when 'GB'
1024**3
when 'TB'
1024**4
when 'PB'
1024**5
when 'EB'
1024**6
when 'ZB'
1024**7
when 'YB'
1024**8
else
1
end
end
end
size_string = "10KB"
size_string.extend(ToBytes).to_bytes
=> 10240
String.include(ToBytes)
"1024 KB".to_bytes
=> 1048576
If you need KiB
, MiB
etc then you just add multipliers.
How can I find the size of an uploaded file in Ruby on Rails?
File.size(doc.filename)
Just throw the name of the file into the curly brackets and you should be set.
If you want KB/MB use:
number_to_human_size(File.size(doc.filename))
EDIT:
You can use the exact path or Pathname
1.9.3p125 :005 > x=Pathname.new("/usr/bin/ruby")
=> #<Pathname:/usr/bin/ruby>
1.9.3p125 :006 > File.size(x)
=> 5488
For extension:
File.extname("test.rb") #=> ".rb"
Stop file write if file size exceeds 500KB ruby on rails
IO#read, takes a bytes argument, so you can specify the size of what you want to read from IO as below:
require 'open-uri'
open('temp/demo.doc', 'wb') do |file|
file << open('http://example.com/demo.doc').read(500000)
end
you can also play with things like file.stat.size
but given you are piping directly to file you would have to do more things to get this to work.
Ruby: Length of a line of a file in bytes?
IO#gets works the same as if you were capturing input from the command line: the "Enter" isn't sent as part of the input; neither is it passed when #gets is called on a File or other subclass of IO, so the numbers are definitely not going to match up.
See the relevant Pickaxe section
May I enquire why you're so concerned about the line lengths summing to the file size? You may be solving a harder problem than is necessary...
Aha. I think I get it now.
Lacking a handy iPod (or any other sort, for that matter), I don't know if you want exactly 4K chunks, in which case IO#read(4000) would be your friend (4000 or 4096?) or if you're happier to break by line, in which case something like this ought to work:
class Chunkifier
def Chunkifier.to_chunks(path)
chunks, current_chunk_size = [""], 0
File.readlines(path).each do |line|
line.chomp! # strips off \n, \r or \r\n depending on OS
if chunks.last.size + line.size >= 4_000 # 4096?
chunks.last.chomp! # remove last line terminator
chunks << ""
end
chunks.last << line + "\n" # or whatever terminator you need
end
chunks
end
end
if __FILE__ == $0
require 'test/unit'
class TestFile < Test::Unit::TestCase
def test_chunking
chs = Chunkifier.to_chunks(PATH)
chs.each do |chunk|
assert 4_000 >= chunk.size, "chunk is #{chunk.size} bytes long"
end
end
end
end
Note the use of IO#readlines to get all the text in one slurp: #each or #each_line would do as well. I used String#chomp! to ensure that whatever the OS is doing, the byts at the end are removed, so that \n or whatever can be forced into the output.
I would suggest using File#write, rather than #print or #puts for the output, as the latter have a tendency to deliver OS-specific newline sequences.
If you're really concerned about multi-byte characters, consider taking the each_byte or unpack(C*) options and monkey-patching String, something like this:
class String
def size_in_bytes
self.unpack("C*").size
end
end
The unpack version is about 8 times faster than the each_byte one on my machine, btw.
Converting filesize string to kilobyte equivalent in Rails
def quota_convert
@regex = /([0-9]+) (.*)s?/
@sizes = "kilobytes megabytes gigabytes"
m = self.quota.match(@regex)
if @sizes.include? m[2]
m[1].to_f.send(m[2])
end
end
- Added
?
for optional plural in the regex. - Changed @sizes to a string of plurals.
- Convert m[1] (the number to a float).
- Send the message m[2] directly
How to stub file size on Active Storage test? (Test::Unit)
I read the code from your project, and I see that you've come up with an interesting solution, but here's another that matches your requirements.
Step 1 - Add mocha
Mocha is the de facto stubbing library for MiniTest fans, so add it to your Gemfile like so.
group :test do
gem 'mocha'
end
Then run bundle install
and require mocha in your test helper like so:
# test/test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require_relative '../config/environment'
require 'rails/test_help'
# add this line
require 'mocha/minitest'
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
end
Step 2 - Create a dummy test file
Place a small file named 'test.png' in test/fixtures/files/
. Note that my file is around 20KB in size, it's pretty small.
Step 3 - Add a unit test
Add the following to test/models/page_test.rb
:
test 'file has max size' do
# get the path of the file
fixture_path = File.join(Rails.root, 'test', 'fixtures', 'files', 'test.png')
# open the file
fixture_file = File.open(fixture_path)
# stub the file size to 21 MB
fixture_file.stubs(:size).returns(21.megabytes)
# attach the file to your @page instance
@page.file.attach(io: fixture_file, filename: 'test.png')
# the record should now be invalid
refute @page.valid?
# it should not have an attachment
refute @page.file.attached?
# assert the error message matches a regex
assert_match /is too big/, @page.errors[:file].to_s
end
Step 4 - Test inside the maximum filesize boundary
Let's make sure that a file of 20MB can be accepted by adding the following to test/models/page_test.rb
:
test 'file with valid size' do
# get the path of the file
fixture_path = File.join(Rails.root, 'test', 'fixtures', 'files', 'test.png')
# open the file
fixture_file = File.open(fixture_path)
# stub the file size to 20 MB
fixture_file.stubs(:size).returns(20.megabytes)
# attach the file to your @page instance
@page.file.attach(io: fixture_file, filename: 'test.png')
# the record should now be valid
assert @page.valid?
# it should have an attachment
assert @page.file.attached?
# probably unnecessary, but let's test that there are no errors on @page
assert_empty @page.errors[:file]
end
Step 5 - Add a controller test for the happy path
Let's add a controller test for the happy path:
test 'should update page' do
# fixture_file_upload knows where the fixtures folder is
# and makes sure we have a correctly signed file
fixture_file = fixture_file_upload('files/test.png', 'image/png')
# we need to stub the byte_size of any instance of ActiveStorage::Blob
# as that is what our validations are going to be run against
ActiveStorage::Blob.any_instance.stubs(:byte_size).returns(20.megabytes)
# make sure our ActiveStorage records are created
assert_difference ['ActiveStorage::Blob.count', 'ActiveStorage::Attachment.count'] do
# add our fixture file into the params
patch page_url, params: { page: { file: fixture_file } }
end
# make sure we are redirected to the right place
assert_redirected_to page_url
end
Step 6 - Add a controller test for the sad path
Time to test upload failure:
test 'should render edit template when update fails' do
# like before, we get correctly formatted test file by calling
# fixture_file_upload method and passing in the test file
fixture_file = fixture_file_upload('files/test.png', 'image/png')
# stub the byte_size to be 21MB
ActiveStorage::Blob.any_instance.stubs(:byte_size).returns(21.megabytes)
# make sure zero ActiveStorage records are created
assert_no_difference ['ActiveStorage::Blob.count', 'ActiveStorage::Attachment.count'] do
# send the request
patch page_url, params: { page: { file: fixture_file } }
end
# check the response body for an error message
assert_match /is too big/, response.body.to_s
end
That's it. Hope it helps.
Related Topics
How to Compare a String Against Multiple Other Strings
Rails Strip Non Numeric Values Before Save
The Encoding That Notepad++ Just Calls "Ansi", Does Anyone Know What to Call It for Ruby
Rails 4 + Devise: Invalid Route Name, Already in Use
Ruby: How to Make Irb Print Structure for Arrays and Hashes
Undefined Instance Method "Respond_To" in Rails 5 API Controller
How to Specify a Required Switch (Not Argument) with Ruby Optionparser
Rbenv: Surviving Without Gemsets
Why Pg::Uniqueviolation: Error: Duplicate Key Value Violates Unique Constraint
How to Sort in Ruby/Rails on Two Fields
Rubygems Do Not Install on Os X Lion
Rake Assets:Precompile Attempting to Connect to Database
Put Haml Tags Inside Link_To Helper
How to Get the Latest Record from Each Group in Activerecord