How to return image with GAE? - python

Each time user accesses http://www.example.com/some-random-symbols-1x1.png, I should return transparent image 1x1px. I've created according file, but how should I read it in my code to return to the user? I know how to display the image from the datastore or blobstore. But have no idea how to read and return binary file.
It can not be static file due to the following reasons:
url will contain some-random-symbols;
once url is accessed, prior to displaying images, I would like to log that somebody accessed the file.

A 1x1 transparent PNG (or GIF) is small enough that you can hard-code the base64 representation directly and emit it directly via self.response.write() (after decoding).
Reading from disk every time is relatively expensive. If you want to go that route, lazily initialize a global variable.

In a more general case, I'd use the blobstore and the BlobstoreDownloadHandler, but for a tiny gif that will definitely fit into memory, something like this to read the file's content:
with open('path/to/file.gif') as f:
img_content = f.read()
I'd put this outside of my handler, so it was done once per instance. If you're using 2.5, then you'll need to import 'with' from future, or open and close the file yourself.
then in your handler, assuming webapp2:
self.response.content_type = 'image/gif'
self.response.write(img_content)

Related

Python - Convert JPG to text file

Good morning all,
I've made a Python script that adds text on top of images, based on a preset template. I'm now developing a template editor that will let the user edit the template in GUI, then save the template as a config file. The idea is that one user can create a template, export it, send it to a new user on a separate computer, who can import it into their config file. The second user will retain full edit abilities on the template (if any changes needs to be made).
Now, in addition to the text, I also want the ability to add up to two images (company logos, ect.) to the template/stills. Now, my question: Is there a way to convert a JPG to pure text data, that can be saved to a config file, and that can be reinterpreted to a JPG at the receiving system. And if not, what would be the best way to achieve this? What I'm hoping to avoid is the user having to send the image files separately.
Sounds questionable that you want to ship an image as text file (it's easy, base64 is supplied with python, but it drastically increases the amount of bytes. I'd strongly recommend not doing that).
I'd rather take the text and embed it in the image metadata! That way, you would still have a valid image file, but if loaded with your application, that application could read the metadata, interpret it as text config.
There's EXIF and XMP metadata, for both there's python modules.
Alternatively, would make more sense to simply put images and config files into one archive file (you know .docx word documents? They do exactly that, just like .odt; java jar files? Same. Android APK files? All archive files with multiple files inside) python brings a zip module to enable you to do that easily.
Instead of an archive, you could also build a PDF file. That way, you could simply have the images embedded in the PDF, the text editable on top of it, any browser can display it, and the text stays editable. Operating on pdf files can be done in many ways, but I like Fitz from the PyMuPDF package. Just make a document the size of your image, add the image file, put the text on top. On the reader side, find the image and text elements. It's relatively ok to do!
PDF is a very flexible format, if you need more config that just text information, you can add arbitrary text streams to the document that are not displayed.
If I understand properly, you want to use the config file as a settings file that stores the preferences of a user, you could store such data as JSON/XML/YAML or similar, such files are used to store data in pure readable text than binary can be parsed into a Python dict object. As for storing the images, you can have the generated images uploaded to a server then use their URL when they are needed to re-download them, unless if I didn’t understand the question?

Restrict Upload of Any Image Other Than a Specific One in Flask or Bottle

It seems that every question related to this one is asking about restricting uploads by file size, etc.
I am creating an online demo of an application using Bottle (similar to Flask). Part of the program requires a user to download a very specific image and then upload it to see the result of a crop operation done on that image. The image is very particular, so I am trying to save the user time in using the demo, but also prevent shifty image files from being uploaded to the server.
My question is, is it possible to restrict the upload to only that particular image. Is there a way to know that an image uploaded is not that exact image?
For stub testing, I just did the following:
myimg = request.files.get("myimg")
fname = myimg.filename
if fname == "bob.jpeg" or fname == "sally.jpeg":
do what the app needs to do
else:
return "Only the demo images are allowed"
Obviously, restricting it by filename is silly because anyone can just rename a new file.
I was thinking perhaps that an image could be turned into some kind of special array, and then I can compare the two arrays, or is there a more elegant solution?
Any help/ideas are appreciated.
To confirm whether the uploaded file is indeed the one you expect, simply examine its bytes and compare them to the known, good, file. You can either checksum the incoming bytes yourself (using, say, hashlib), or use filecmp.cmp (which I think is simpler, assuming you have a copy of the acceptable image on disk where the server can read it).
For example:
uploaded_img = request.files.get("myimg")
if not filecmp.cmp(uploaded_img.filename, "/path/to/known/good/image", shallow=False):
raise ValueError("An unexpected file was uploaded")

Python and Django - How to use in memory and temporary files

I need some examples with file operations using in memory and temporary files.
I searched a lot for a good example /tutorial and I found just basic read/write/append operations.
I need to understand how can I read in Django a file that is uploaded(an image) before the save(post) is finished.
Because Django is Python, I think is better to understand first in python.
I checked the Django documentation/examples about, but it is not very clear so I need to understand first in Python then in Django how the operations are working, not just copy and paste.
I know how to use ImageFields, upload default operation, I'm interested only in using "in memory and temporary files."
I want to use this in combination with a crop function. So the user can upload 1, 2, 3... images, and with a javascript crop script I get the coordinates in a hidden field. After javascript simulated crop I show the user a thumbnail with the crop, how will look like ratio
The user can change his mind and can edit/update or delete a file before saving.
Now depending on the file size it can be keep in memory or write.
When a file is uploaded Django will do one of two things: store it in memory if the file is small (< 2 MB last time I checked), or store it as a temporary file on disk if it's large. This behavior is configurable via the FILE_UPLOAD_HANDLERS setting. So, your web server and Django take care of the actual upload and storage, but it's your job to process the file before the request is over, otherwise the file is deleted.
Uploaded files are accessible through the request.FILES property. Each key in FILES will match the name of the file input on your <form>. The value is an UploadedFile object, which is a stream you can use to read the file data.
For example, say you have an <input name="img" type="file" /> and you want to detect if the image is completely white. You don't need to store the file for this, you just need to load it into memory, process it to get the result and then let it be discarded.
from PIL import Image
def some_view(request):
if request.method == 'POST':
img_file = request.FILES['img']
if img_file.size > 2000000:
return HttpResponseBadRequest()
img = Image.open(img_file)
# analyze the image...
Another possibility is that someone is uploading a backup file that is quite large (lets say 2 GB), and you need to store it somewhere. It's effectively the same thing, except we read the file into memory in chunks, then write each chunk to disk somewhere else so that it's saved after the request finishes.
def some_view(request):
if request.method == 'POST':
backup_file = request.FILES['backup_file']
with open('some/file/name.bak', 'wb+') as destination:
for chunk in backup_file.chunks():
destination.write(chunk)
# file is saved
When the request is over, the uploaded file is stored at some/file/name.bak.
Whether it's in memory or a temporary file is usually not important because the interface is the same. You can read a temporary file just like you can read an in memory file.
You can set which upload handler is used for a Django form: https://docs.djangoproject.com/en/1.11/ref/files/uploads/#module-django.core.files.uploadhandler
There are two built in options:
in memory
temporary file
The way Django seems to work is by walking through the list of all upload handlers: https://docs.djangoproject.com/en/1.11/topics/http/file-uploads/#upload-handlers
For each upload handler it will check for a specific condition and if that condition is true, it will activate and use that upload handler.
The InMemoryUploadHandler, for example, is activated and used when files are below a certain size. The TemporaryFileUploadHandler is used when files are very large.
You will be able to access the data and files from the request object.
If you're looking at Python specific (not Django), then it sounds like you may be interested in the tempfile module:
https://docs.python.org/3/library/tempfile.html
Adapting the example from the document above:
import tempfile
fp = tempfile.TemporaryFile()
fp.write(b'Hello world!')
# Closing automatically deletes the tempfile
fp.close()
You can see this works fairly similarly to generic read/write file operations.
If I understand correctly you are looking for a way to access the uploaded file before it is saved using instance.save() or similar.
If that is the case, you might try to read the file directly from request:
if my_form.is_valid():
data = request.FILES['myfile'].read()

Upload image with an in-memory stream to input using Pillow + WebDriver?

I'm getting an Image from URL with Pillow, and creating an stream (BytesIO/StringIO).
r = requests.get("http://i.imgur.com/SH9lKxu.jpg")
stream = Image.open(BytesIO(r.content))
Since I want to upload this image using an <input type="file" /> with selenium WebDriver. I can do something like this to upload a file:
self.driver.find_element_by_xpath("//input[#type='file']").send_keys("PATH_TO_IMAGE")
I would like to know If its possible to upload that image from a stream without having to mess with files / file paths... I'm trying to avoid filesystem Read/Write. And do it in-memory or as much with temporary files. I'm also Wondering If that stream could be encoded to Base64, and then uploaded passing the string to the send_keys function you can see above :$
PS: Hope you like the image :P
You seem to be asking multiple questions here.
First, how do you convert a a JPEG without downloading it to a file? You're already doing that, so I don't know what you're asking here.
Next, "And do it in-memory or as much with temporary files." I don't know what this means, but you can do it with temporary files with the tempfile library in the stdlib, and you can do it in-memory too; both are easy.
Next, you want to know how to do a streaming upload with requests. The easy way to do that, as explained in Streaming Uploads, is to "simply provide a file-like object for your body". This can be a tempfile, but it can just as easily be a BytesIO. Since you're already using one in your question, I assume you know how to do this.
(As a side note, I'm not sure why you're using BytesIO(r.content) when requests already gives you a way to use a response object as a file-like object, and even to do it by streaming on demand instead of by waiting until the full content is available, but that isn't relevant here.)
If you want to upload it with selenium instead of requests… well then you do need a temporary file. The whole point of selenium is that it's scripting a web browser. You can't just type a bunch of bytes at your web browser in an upload form, you have to select a file on your filesystem. So selenium needs to fake you selecting a file on your filesystem. This is a perfect job for tempfile.NamedTemporaryFile.
Finally, "I'm also Wondering If that stream could be encoded to Base64".
Sure it can. Since you're just converting the image in-memory, you can just encode it with, e.g., base64.b64encode. Or, if you prefer, you can wrap your BytesIO in a codecs wrapper to base-64 it on the fly. But I'm not sure why you want to do that here.

How to display pyBarcode generated image on web without saving

I want to display the png or svg barcode generated by pyBarcode on a webpage. But I'm thinking it would be better if I don't have to save the image on the server. Is there anyway I can do this with pyBarcode? or with any other barcode image generation method with python?
I'm using pyramid as the web framework, if that changes anything.
Write the barcode straight out to the response.body_file:
barcode.writer import ImageWriter
ean = barcode.get_barcode('ean', '123456789102', writer=ImageWriter())
response = request.response
response.content_type = 'image/png'
ean.write(response.body_file)
I do not see how you can serve a file thats not even created . Consider saving it in /tmp if it won't be required for a long time but you will create and serve it once.
You should be able to do this by creating a HTTP response that returns the file object.
So that the request to "http://mysite.com/someimage.png" returns the file contents.
Try writing to the pyramid.response.Response object's .body_file.

Categories

Resources