I'm using ruby on rails to modify a powerpoint presentations existing template's xml files (open xml) based on data from my postgres database.
The issue I am facing is that after the file is generated and downloaded from heroku using a windows machine, microsoft powerpoint detects the file as corrupted and attempts to repair. After repairing the file generated in powerpoint, the file opens correctly.
If i download the file from a Linux machine and send the file to a windows machine, the file opens correctly without warning or attempt to repair. The powerpoint generated also opens correctly on Open office.
Technically, these are the steps that I am using to generate the file.
- Open the template from the assets folder of my application
- Extract the files in a tmp folder using Rubyzip gem
- Open and modify the individual files using Nokogiri
- Compress the file to a .pptx file
- Upload/Save file using active storage
Redirect user to the file for download
Extract files method
def self.extract_files(dir_prefix)
Zip::File.open(Rails.root.join('app', "assets", "ppt", 'test_8.pptx')) do |z| z.each do |f| ##Extract files in a directory f_path=File.join("tmp/#{dir_prefix}_destination", f.name) FileUtils.mkdir_p(File.dirname(f_path)) z.extract(f, f_path) unless File.exist?(f_path) end end
end
Opening files for manipulations using:
chartxml = File.open(Rails.root.join('tmp', tmp_extract_folder, 'ppt', 'charts', 'chart5.xml'))
##Manipulation logic here
File.write(Rails.root.join('tmp', tmp_extract_folder, 'ppt', 'charts', 'chart5.xml'), doc.to_xml)
Re-zipping files using:
zf =ZipFileGenerator.new("tmp/#{dir_prefix}_destination", "tmp/#{dir_prefix}_zipped.pptx")
The implementation of the zip file generator is the same as the one provided on Rubyzip's github repo
I'm then storing using active storage using:
ppt = Powerpoint.new(name: "#{dir_prefix}")
ppt.file.attach(
io: File.open("tmp/#{dir_prefix}_zipped.pptx"), filename: 'Synthese.pptx', content_type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
)
ppt.save
render :js => "window.location = '#{download_ppt_path(dir_prefix: dir_prefix)}'"
The user then downloads the file:
ppt = Powerpoint.where(name: dir_prefix)
redirect_to rails_blob_path(ppt.first.file, disposition: "attachment")
I tried uncommenting the code which does the manipulation of the xml files, and just unzipping and rezipping; I still face the same issue.