Python - save BytesIO in database - python

So I am trying to create a binary file and save it into my database. I am using REDIS and SQLALCHEMY as a framework for my database. I can use send_file to send the actual file whenever the user accesses a URL but how do I make sure that the file is saved in the route and it could stay there every time a user accesses the URL.
I am sending the file from a client-python it's not in my
directory
what I need in a nutshell is to save the file from the client-python to a database to "downloadable" it to the browser-client so it would actually be available for the browser-client is there any way of doing this? Maybe a different way that I didn't think about

I had to encode the data with base64, send it to the database and then decode it and send the file as binary data.

Related

Python Flask Uploading FIles

I'm trying to upload user selected image into my firebase.
When I browse for the file
file = request.files['inputFile']
and I try this
storage.child("images/examples.jpg").put(file)
I get an error
io.UnsupportedOperation: fileno
How do I go about fixing this? I just want user to select the file and I be able to make use of the .jpg file and upload it
The put method takes a path to a local file (and an optional user token).
request.files[key] returns a custom object that represents the uploaded file. Flask documentation links: file uploads quickstart, incoming request data api, FileStorage class.
You need to store the uploaded file data to a local file, and the pass that file name to the put method:
request.files['inputFile'].save("some_filename.ext")
storage.child("images/examples.jpg").put("some_filename.ext")
Look into the tempfile module to generate random temporary file names (instead of using the hard coded some_filename.ext, which obviously is not a very good idea with concurrent requests).

Python API: Tweet with media without file

I'm using twitter from python in an environment where I can't store files.
I get a HTTP POST with a text and an image and want to create a tweet from this data without writing a local file (it's zappa on AWS api environment).
Tweepy only allows filenames, which does not work for me.
python-twitter seems to have something like that, but I can't find a doc for this.
Should I just send POST requests to twitter for uploading the images? Is there a simpler way?
Try passing a io.BytesIO to tweepy's API.update_with_media as file.
filename – The filename of the image to upload. This will automatically be opened unless file is specified
...
file – A file object, which will be used instead of opening filename. filename is still required, for MIME type detection and to use as a form field in the POST data
Edit:
It looks like you have the image data base64 encoded. You can use base64.b64decode to decode it before creating the io.BytesIO:
file = io.BytesIO(base64.b64decode(base64_data))

Using memcached to host images

Im writing simple blogging platform in Flask microframework, and I'd like to allow users to change image on the front page but without actually writing it into filesystem. Is it possible to point src attribute in img tag to an object stored in memory?
Yes, you can do it.
Create a controller or serlvet called for example
www.yoursite.com/getImage/ID
When you execute this URL, your
program shoud connect to the memcached and return the image object
that you have previously stored in it.
Finally when in your html you add: src="www.yoursite.com/getImage/ID" the browser will execute
this url, but instead of reading a file from disk it will ask the memcached for the specific ID.
Be sure to add the correct content-type in your response from the server in order that the browser understand that you are sending an image content.
Fer

Python: Create and return an SQLite DB as a web request result

In my python/django based web application I want to export some (not all!) data from the app's SQLite database to a new SQLite database file and, in a web request, return that second SQLite file as a downloadable file.
In other words: The user visits some view and, internally, a new SQLite DB file is created, populated with data and then returned.
Now, although I know about the :memory: magic for creating an SQLite DB in memory, I don't know how to return that in-memory database as a downloadable file in the web request. Could you give me some hints on how I could reach that? I would like to avoid writing stuff to the disc during the request.
I'm not sure you can get at the contents of a :memory: database to treat it as a file; a quick look through the SQLite documentation suggests that its API doesn't expose the :memory: database to you as a binary string, or a memory-mapped file, or any other way you could access it as a series of bytes. The only way to access a :memory: database is through the SQLite API.
What I would do in your shoes is to set up your server to have a directory mounted with ramfs, then create an SQLite3 database as a "file" in that directory. When you're done populating the database, return that "file", then delete it. This will be the simplest solution by far: you'll avoid having to write anything to disk and you'll gain the same speed benefits as using a :memory: database, but your code will be much easier to write.
With web content you can easily serve files as raw binary with a content type specified in the response.
Django makes this fairly easy - here's a snippet I use on one of my sites for generating a barcode for a user.
def barcode(request):
from core import ugbarcode
bar = ugbarcode.UGBar("0001")
binStream = bar.asString('gif')
return HttpResponse(binStream, 'image/gif')
See also this post for more details in specifying it is an attachment to trigger download: Generating file to download with Django

What's a Django/Python solution for providing a one-time url for people to download files?

I'm looking for a way to sell someone a card at an event that will have a unique code that they will be able to use later in order to download a file (mp3, pdf, etc.) only one time and mask the true file location so a savvy person downloading the file won't be able to download the file more than once. It would be nice to host the file on Amazon S3 to save on bandwidth where our server is co-located.
My thought for the codes would be to pre-generate the unique codes that will get printed on the cards and store those in a database that could also have a field that stores the number of times the file was downloaded. This way we could set how many attempts we would allow the user for downloading the file.
The part that I need direction on is how do I hide/mask the original file location so people can't steal that url and then download the file as many times as they want. I've done Google searches and I'm either not searching using the right keywords or there aren't very many libraries or snippets out there already for this type of thing.
I'm guessing that I might be able to rig something up using django.views.static.serve that acts as a sort of proxy between the actual file and the user downloading the file. The only drawback to this method I would think is that I would need to use the actual web server and wouldn't be able to store the file on Amazon S3.
Any suggestions or thoughts are greatly appreciated.
Neat idea. However, I would warn against the single-download method, because there is no guarantee that their first download attempt will be successful. Perhaps use a time-expiration method instead?
But it is certainly possible to do this with Django. Here is an outline of the basic approach:
Set up a django url for serving these files
Use a GET parameter which is a unique string to identify which file to get.
Keep a database table which has a FileField for the file to download. This table maps the unique strings to the location of the file on the file system.
To serve the file as a download, set the response headers in the view like this:
(path is the location of the file to serve)
with open(path, 'rb') as f:
response = HttpResponse(f.read())
response['Content-Type'] = 'application/octet-stream';
response['Content-Disposition'] = 'attachment; filename="%s"' % 'insert_filename_here'
return response
Since we are using this Django page to serve the file, the user cannot find out the original file location.
You can just use something simple such as mod_xsendfile. This functionality is also available in other popular webservers such lighttpd or nginx.
It works like this: when enabled your application (e.g. a trivial PHP script) can send a special response header, causing the webserver to serve a static file.
If you want it to work with S3 you will need to handle each and every request this way, meaning the traffic will go through your site, from there to AWS, back to your site and back to the client. Does S3 support symbolic links / aliases? If so you might just redirect a valid user to one of the symbolic URLs and delete that symlink after a couple of hours.

Categories

Resources