I'm using Selenium Grid and I need to download files for the automated tests download. I'm running into an issue where the response is not the file contents itself. Instead, the contents are zipped first and then wrapped within JSON.
Here's the response I'm trying to unzip:
b'{\n "filename": "test.txt",\n "contents": "UEsDBBQACAgIAFV1TlYAAAAAAAAAAAAAAAAIAAAAdGVzdC50eHQDAFBLBwgAAAAAAgAAAAAAAABQSwECFAAUAAgICABVdU5WAAAAAAIAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAdGVzdC50eHRQSwUGAAAAAAEAAQA2AAAAOAAAAAAA"\n}'
The data above should contain an empty file called test.txt.
According to the documentation, the contents are a zipped folder in Base64 encoding. I want to be able to unzip this string and read the contents of the test.txt file within, but I'm not sure how to unzip a byte string with an encoding of base 64.
I'm using Python so if anyone knows how to unzip the contents and read the test.txt file within that would be extremely helpful.
Here's the documentation on Selenium Grid for Downloading files:
https://www.selenium.dev/documentation/grid/configuration/cli_options/#important-information-when-dowloading-a-file
You will need to b64decode the contents after the json has been parsed, and then store the result in either a temporary file or a BytesIO object for it to be usable with ZipFile:
import json
from base64 import b64decode
from io import BytesIO
from pathlib import Path
from zipfile import ZipFile
data = b'{\n "filename": "test.txt",\n "contents": "UEsDBBQACAgIAFV1TlYAAAAAAAAAAAAAAAAIAAAAdGVzdC50eHQDAFBLBwgAAAAAAgAAAAAAAABQSwECFAAUAAgICABVdU5WAAAAAAIAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAdGVzdC50eHRQSwUGAAAAAAEAAQA2AAAAOAAAAAAA"\n}'
contents = json.loads(data)['contents']
bio = BytesIO(b64decode(contents))
We can then see the metadata about the files stored within that zip file (this step is not required):
>>> with ZipFile(bio) as zip_file:
... zip_file.infolist()
...
[<ZipInfo filename='test.txt' compress_type=deflate file_size=0 compress_size=2>]
To extract all files, you can use the extractall method:
>>> path = Path('temp/extracted')
>>> path.mkdir()
>>> with ZipFile(bio) as zip_file:
... zip_file.extractall(path)
...
>>> for p in path.iterdir():
... print(p.as_posix())
...
temp/extracted/test.txt
It is also possible to extract individual files, if desired.
What is the way to get file type from base64 string?
I need a solution which will work on Windows and Linux(Centos7)
E.G.: This is string ; eHh4eHh4 which is = to a text file with xxxxxx inside.
If websites can do this, I guess it is possible to do it in python:
https://base64.guru/converter/decode/file
What I have tried:
using magic
using imghdr
You could write the base64 content into BytesIO:
import base64
import magic # https://pypi.org/project/python-magic/
import io
data = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+P+/HgAFhAJ/wlseKgAAAABJRU5ErkJggg=='
bytesData = io.BytesIO()
bytesData.write(base64.b64decode(data))
bytesData.seek(0) # Jump to the beginning of the file-like interface to read all content!
print(magic.from_buffer(bytesData.read()))
Out:
PNG image data, 1 x 1, 8-bit/color RGBA, non-interlaced
I have the following program:
import fileinput
import base64
for index, line in enumerate(fileinput.input('input1.txt'), 1):
if line.startswith('data:image/jpeg;base64,'):
with open('image{0:04}.jpeg'.format(index), 'wb') as jpeg:
line = line.strip()
jpeg.write(base64.b64decode(line[22:] + '===='))
Intent is to pick base64 data from a file and create jpeg files from it. But somehow it is not identifying the starting characters as jpeg (have tried using jpg) and is skipping the data.
Thanks #jps and #vishnudev. It works fine with the following changes.
for index, line in enumerate(fileinput.input('input1.txt'), 1):
with open('image{0:02}.jpg'.format(index), 'wb') as jpg:
line = line.strip()
jpg.write(base64.b64decode(line))
I am trying to use PIL.Image.open to open the image from an opened json file. Should I just put the name of the png file inside the Image.open() or is it the directory that leads to the json file?
Thanks
Here is a full example which is probably what you're looking for:
import json
from PIL import Image
with open('yourfilename.txt', 'r') as f:
data = json.load(f)
# Load the file path from the json
imgpath = data['yourkey']
# Place the image path into the open method
img = Image.open(imgpath)
The imgpath variable should return a string of the path to your image.
Pillows Image.open docs
I want to encode an image into a string using the base64 module. I've ran into a problem though. How do I specify the image I want to be encoded? I tried using the directory to the image, but that simply leads to the directory being encoded. I want the actual image file to be encoded.
EDIT
I tried this snippet:
with open("C:\Python26\seriph1.BMP", "rb") as f:
data12 = f.read()
UU = data12.encode("base64")
UUU = base64.b64decode(UU)
print UUU
self.image = ImageTk.PhotoImage(Image.open(UUU))
but I get the following error:
Traceback (most recent call last):
File "<string>", line 245, in run_nodebug
File "C:\Python26\GUI1.2.9.py", line 473, in <module>
app = simpleapp_tk(None)
File "C:\Python26\GUI1.2.9.py", line 14, in __init__
self.initialize()
File "C:\Python26\GUI1.2.9.py", line 431, in initialize
self.image = ImageTk.PhotoImage(Image.open(UUU))
File "C:\Python26\lib\site-packages\PIL\Image.py", line 1952, in open
fp = __builtin__.open(fp, "rb")
TypeError: file() argument 1 must be encoded string without NULL bytes, not str
What am I doing wrong?
I'm not sure I understand your question. I assume you are doing something along the lines of:
import base64
with open("yourfile.ext", "rb") as image_file:
encoded_string = base64.b64encode(image_file.read())
You have to open the file first of course, and read its contents - you cannot simply pass the path to the encode function.
Edit:
Ok, here is an update after you have edited your original question.
First of all, remember to use raw strings (prefix the string with 'r') when using path delimiters on Windows, to prevent accidentally hitting an escape character. Second, PIL's Image.open either accepts a filename, or a file-like (that is, the object has to provide read, seek and tell methods).
That being said, you can use cStringIO to create such an object from a memory buffer:
import cStringIO
import PIL.Image
# assume data contains your decoded image
file_like = cStringIO.StringIO(data)
img = PIL.Image.open(file_like)
img.show()
The first answer will print a string with prefix b'.
That means your string will be like this b'your_string' To solve this issue please add the following line of code.
encoded_string= base64.b64encode(img_file.read())
print(encoded_string.decode('utf-8'))
I have experienced this while converting Image to Base64 string. You can take a look at how I removed that from there also. Link is here Image to base64 string and fix 'b from prefix
import base64
from PIL import Image
from io import BytesIO
with open("image.jpg", "rb") as image_file:
data = base64.b64encode(image_file.read())
im = Image.open(BytesIO(base64.b64decode(data)))
im.save('image1.png', 'PNG')
Borrowing from what Ivo van der Wijk and gnibbler have developed earlier, this is a dynamic solution
import cStringIO
import PIL.Image
image_data = None
def imagetopy(image, output_file):
with open(image, 'rb') as fin:
image_data = fin.read()
with open(output_file, 'w') as fout:
fout.write('image_data = '+ repr(image_data))
def pytoimage(pyfile):
pymodule = __import__(pyfile)
img = PIL.Image.open(cStringIO.StringIO(pymodule.image_data))
img.show()
if __name__ == '__main__':
imagetopy('spot.png', 'wishes.py')
pytoimage('wishes')
You can then decide to compile the output image file with Cython to make it cool. With this method, you can bundle all your graphics into one module.
As I said in your previous question, there is no need to base64 encode the string, it will only make the program slower. Just use the repr
>>> with open("images/image.gif", "rb") as fin:
... image_data=fin.read()
...
>>> with open("image.py","wb") as fout:
... fout.write("image_data="+repr(image_data))
...
Now the image is stored as a variable called image_data in a file called image.py
Start a fresh interpreter and import the image_data
>>> from image import image_data
>>>
Its work for me
import base64
import requests
# Getting image in bytes
response = requests.get("image_url")
# image encoding
encoded_image = base64.b64encode(response.content)
# image decoding and without it's won't work due to some '\xff' error
decoded_image= base64.b64decode(encoded_image)