Skip to content
This repository has been archived by the owner on Jul 13, 2023. It is now read-only.

Uploading Tempfiles results in blank files, but only sometimes #2633

Open
jjb opened this issue Mar 4, 2019 · 0 comments
Open

Uploading Tempfiles results in blank files, but only sometimes #2633

jjb opened this issue Mar 4, 2019 · 0 comments

Comments

@jjb
Copy link
Contributor

jjb commented Mar 4, 2019

rails 5.1.6.1
ruby 2.5.3
paperclip 6.0.0

I have code like this:

def my_method(file_name, data, headers)
  file = Tempfile.new([file_name, ".csv"])
  csv = CSV.new(file, write_headers: true, headers: headers)
  data.each do |row|
    csv << row
  end

  #############
  file.rewind #
  #############

  o = MyModel.create!
  o.file = file
  o.file.instance_write(:file_name, "#{file_name}.csv")
  mime_type = MIME::Types.type_for(file.path).last.to_s
  o.file.instance_write(:content_type, mime_type)
  o.file.options.merge({:s3_headers => {"Content-Type" => mime_type, "Content-Disposition" =>  "attachment; filename='#{o.file_file_name}'"}})
  o.save!
  o
ensure
  file.close
  file.unlink
end

When file.rewind is not there, then some files will end up being uploaded as blank files and some will not.

When file.rewind is there, then the file always gets uploaded correctly.

First explanation that comes to mind is something to do with file size (although our samples of working and non-working instances don't really suggest that that's the reason, but I haven't explored this thoroughly). Maybe CSV doesn't flush until a certain size of file has been processed. This didn't pan out because:

  • does rewind result in a flush first? I'm guessing not
  • i experimented with a very simple script (below) and things behave as expected. rewind is necessary to read from the file (which makes sense — only the block form of CSV might be expected to flush, close, and/or rewind a file)
  • csv seems to always flush on each input of a new row (although discussion found while googling seems to suggest otherwise — maybe the block form of CSV keeps a buffer?)

Which is all to say that it seems like it's paperclip which is the one that sometimes rewinds, sometimes does not.

Searching the codebase for this behavior led me nowhere.

Can someone point me in the right direction on where the relevant code in paperclip might be?

And/or does someone doubt that the non-rewind version ever worked? I'm quite certain that it did. But if this seems preposterous to someone, then I'll set up an environment with my old code and check again.

Thanks! Let me know any questions!

require "csv"
require "tempfile"

headers = ["name", "email"]

file1 = Tempfile.new(["file1", ".csv"])
csv1 = CSV.new(file1, write_headers: true, headers: headers)
csv1 << [1,2]
puts "file1"
#file1.rewind                                                                                                                                                               
#puts file1.flush                                                                                                                                                           
puts file1.read[0..30]

file2 = Tempfile.new(["file2", ".csv"])
csv2 = CSV.new(file2, write_headers: true, headers: headers)
1000000.times{csv2 << [1,2]}
puts "file2"
#file2.rewind                                                                                                                                                               
#puts file2.flush                                                                                                                                                           
puts file2.read[0..30]

puts "end"
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant