web2py changes file extension of the uploaded file to txt - upload

I am using fine-uploader.js and fine-uploader.css for uploading my files using web2py framework.
The callback in the controller is
def upload_callback():
if 'qqfile' in request.vars:
filename = request.vars.qqfile
newfilename = db.doc.filename.store(request.body, filename)
db.doc.insert(filename=newfilename,uploaded_by=auth.user.id)
return response.json({'success': 'true'})
The Model
uploadfolder = os.path.join(request.folder, 'uploads')
db.define_table('doc',
Field('name', requires = IS_NOT_EMPTY()),
Field('filename', 'upload',autodelete=True,uploadfolder=uploadfolder),
Field('uploaded_by', db.auth_user)
)
When I upload file 'test01.xls', web2py stores it in file "doc.filename.bfbf907529358f82.7830302729.txt"
I do not understand why the extension xls is being changed to txt. I have also tried uploading a jpg file. Web2py changes the extension of the uploaded file to txt. Can somebody help me.

As request.vars.qqfile is not the filename but a cgi.FieldStorage object, you cannot use it as the filename but must instead extract the filename from it:
filename = request.vars.qqfile.filename
Alternatively, you can simply pass the FieldStorage object directly to the .insert method, and web2py will automatically handle extracting the filename and saving the file:
def upload_callback():
if 'qqfile' in request.vars:
db.doc.insert(filename=request.vars.qqfile, uploaded_by=auth.user.id)
return response.json({'success': 'true'})

Related

Confusion about creating and writing to File in Ruby on rails

I am trying to create a new file and then write some content to it just to create a basic backup of a template.
When I log out the values of filename and file_content they are correct, but when I send the data all I get is a file named after the method (download_include) and a fixnum inside the file, the last one made was 15.
# POST /download_include/:id
def download_include
#include = Include.find(params[:id])
version_to_download = #include.latest_version_record
filename = "#{version_to_download.name}"
file_content = "#{version_to_download.liquid_code.to_s}"
file = File.open(filename, "w") { |f| f.write (file_content) }
send_data file
end
I also tried send_file but that produces the error
no implicit conversion of Fixnum into String
I also tried to just write dummy values like below, and it still produced a file named after the method with a fixnum inside it.
file = File.open("DOES THIS CHANGE THE FILENAME?", "w") { |f| f.write ("FILE CONTENT?") }
I feel I am missing something obvious but I cannot figure it out after looking at many examples here and in blogs.
If you don't end along the filename as an option for send_data, it defaults to the method name.
Secondly, the download wants to read the data from a buffer. My guess is your syntax is just sending a file handle.
Try this...
send_data(file.read, filename: filename)
Or skip the intermediate file and try...
send_data(version_to_download.liquid_code.to_s, filename: filename)

Testing File Creation in Rails

My App saves Files to the Filesystem via an base64 encoded API. Here is my (simplified) controller:
def create
file = "name.pdf"
folder = "downloads"
FileUtils::mkdir_p folder
f = File.open File.join(folder, file), "wb"
if f.write Base64.decode64(params[:file])
f.close
end
Now I want to test for an actual file creation. How do I check whether there is a file or not?
Thanks for your input!

Serving excel sheet (.xls) to browser for download using rails & angular

I am using spreadsheet gem to generate .xls file. After writing it to a file, I am trying to send to client browser for download.
Below is the code in rails
workbook = Spreadsheet::Workbook.new
# Constructed the data
file = "/path/to/file/sheet.xls"
workbook.write file
send_file file
This file when opened contains expected data in ideal format.
Below is the code in js:
CustomRestService.custom_post("report",{report_data: angular.toJson($scope.report_data)},"download_xls",{}).then (data)->
if data
hiddenElement = document.createElement('a')
angular.element(document.body).append(hiddenElement)
hiddenElement.href = 'data:attachment/xls,' + encodeURI(data)
hiddenElement.target = '_blank'
hiddenElement.download = "report.xls"
hiddenElement.click()
hiddenElement.remove()
But the file getting downloaded in browser contains junk data. I tried multiple solutions like below:
Using send_data, instead of send_file
Generated xls data and wrote to StringIO object to directly download
Constructed Blob object in js, with type as "application/vnd.ms-excel" and trying to download it.
All attempts failed, as I am missing something. All suggestions are welcome.
filename = "/path/to/file/sheet.xls"
tempfile = Tempfile.new(filename)
workbook = Spreadsheet::Workbook.new
...
workbook.write(tempfile.path)
send_file tempfile.path, :filename => filename

Django Custom File Storage - write contents to file

I'm trying to write a custom django backend that writes the contents of an uploaded file to an output file while also saving the file as it normally would. I assumed I could do this by overriding the _open function of Django, but no luck. Anyone know how to accomplish this? Here's what I've been messing around with
from django.core.files.storage import FileSystemStorage
class TestStore(FileSystemStorage):
def _open(self, name, mode='rb'):
data = open(name, 'rb')
dataRead = data.read()
filename = '/home/somewhere/testdir/output.txt'
FILE = open(filename, 'w')
FILE.write(dataRead)
FILE.close()
data.close()
return name
If you already created the file you can just output it with content-disposition:
response = HttpResponse(data, content_type='text/txt')
response['Content-Disposition'] = 'attachment; filename=filename'

Sending uploaded file to resque worker to be processed

I just started using resque to do some processing on some very large files in the background, and I'm having trouble figuring out how to pass a file to a resque worker. I use rails to handle the file upload, and rails creates an ActionDispatch::Http::UploadedFile object for each file uploaded from the form.
How do send this file to a resque worker? I tried sending a custom hash of just the pathname of the temporary file and original filename, but I can't reopen the temporary file in the resque worker anymore (just a normal Errno::ENOENT - No such file or directory) because rails seems to delete that temporary file after the request ends.
Http::UploadedFileisn't accessible once the request finishes. You need to write the file somewhere (or use s3 as temp storage). Pass resque the path to the file that you wrote.
I just spent two days trying to do this and finally figured it out. You need to Base64 encode the file so that it can be serialized into json. Then you need to decode it in the worker and create a new
ActionDispatch::Http::UploadedFile
Here's how to encode and pass to resque:
// You only need to encode the actual file, everything else in the
// ActionDispatch::Http::UploadedFile object is just string or a hash of strings
file = params[:file] // Your ActionDispatch::Http::UploadedFile object
file.tempfile.binmode
file.tempfile = Base64.encode64(file.tempfile.read)
Resque.enqueue(QueueWorker, params)
And Here's how to decode and convert back to an object within your worker
class QueueWorker
#queue = :main_queue
def self.perform(params)
file = params['file']
tempfile = Tempfile.new('file')
tempfile.binmode
tempfile.write(Base64.decode64(file['tempfile']))
// Now that the file is decoded you need to build a new
// ActionDispatch::Http::UploadedFile with the decoded tempfile and the other
// attritubes you passed in.
file = ActionDispatch::Http::UploadedFile.new(tempfile: tempfile, filename: file['original_filename'], type: file['content_type'], head: file['headers'])
// This object is now the same as the one in your controller in params[:file]
end
end

Resources