I am trying to save a blob sent via ajax, as a file in python. Had been through this before Python: How do I convert from binary to base 64 and back?
class SaveBlob(APIView):
def post(self, request):
vid = open("file.webm", "wb")
video_stream = request.FILES['blob'].read()
video_stream = struct.pack(video_stream).encode('base64')
# vid.write(video_stream.decode('base64'))
vid.write(video_stream)
vid.close()
return Response()
It results in error: bad char in struct format
Simply using this vid.write(video_stream.decode('base64'))
without usingstruct.pack saves the file but when I open the video it results in could not determine type of stream.
The ajax call goes like this but it looks fine I guess.
function call_ajax(request_type,request_url,request_data) {
var data_vid = new FormData();
console.log(request_url);
data_vid.append('blob', request_data);
console.log(request_data);
var data= [];
try{
$.ajax({
type: request_type,
url: request_url,
data:data_vid,
cors:true,
processData: false,
contentType: false,
async:false,
beforeSend: function(xhr) {
xhr.setRequestHeader('X-CSRFToken',Cookies.get('csrftoken'))
},
success: function(response){
data =response;
}
});
}catch(error){
console.log(error);
}
return data;
}
Any help with it will be appreciated. Any suggestions about any flaws or possible causes are welcome.
You could try using Python's base64 library to encode and decode data in your SaveBlob class:
import base64
video_stream = b"hello"
# Save the binary blob as base64
with open('file.webm', 'wb') as f_vid:
f_vid.write(base64.b64encode(video_stream))
# Read back the binary blob from base64
with open('file.webm', 'rb') as f_vid:
video_stream = base64.b64decode(f_vid.read())
print(video_stream)
Giving you back the original video_stream:
hello
For this simple example, the saved file would appear as:
aGVsbG8=
The first argument to struct.pack is a format string that specifies the layout of the struct. You are only passing the bytes that you want to pack, so this is interpreted as an invalid format:
>>> bs = b'\x01\x56\x56'
>>> struct.pack(bs)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
struct.error: bad char in struct format
Constructing a valid format string fixes this (but note the you need to construct the format string based on your data and platform):
>> n = len(bs) # 3
>>> fmt = '{:d}s'.format(n) # '3s'
>>> struct.pack(fmt, bs)
b'\x01VV'
It's unlikely to be necessary to pack* or base64-encode the data if it's just being written to disk; just write the bytes to file directly:
class SaveBlob(APIView):
def post(self, request):
with open("file.webm", "wb") as vid:
video_stream = request.FILES['blob'].read()
vid.write(video_stream)
return Response()
Your video player should be able to read the binary file and interpret it correctly.
Base64 encoding is really for transferring binary data when the transfer mechanism expects ascii-encoded data, so there's no benefit in applying this encoding just to write to a file. If you really need to base64-encode your data, use the python's base64 package as Martin Evans recommends in his answer..
* It may be necessary to pack the data if it's being moved between platforms with different endianness.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With