javascript 在python中将blob保存到文件中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46090229/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 06:27:00  来源:igfitidea点击:

Saving a blob to a file in python

javascriptpython

提问by Akshay Hazari

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?

我正在尝试将通过 ajax 发送的 blob 保存为 python 中的文件。在Python之前已经经历过这个:如何从二进制转换为 base 64 并返回?

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

它导致 error: bad char in struct format

Simply using this vid.write(video_stream.decode('base64')) without usingstruct.packsaves the file but when I open the video it results in could not determine type of stream.

简单地使用它vid.write(video_stream.decode('base64')) 而不使用struct.pack保存文件但是当我打开视频时它导致无法确定流的类型。

The ajax call goes like this but it looks fine I guess.

ajax 调用是这样的,但我猜它看起来不错。

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.

任何有关它的帮助将不胜感激。欢迎任何关于任何缺陷或可能原因的建议。

采纳答案by Akshay Hazari

The other solutions were helpful where it would write the file to the disk still it would say incorrect file format or unable to play the file because of missing plugins.

其他解决方案在将文件写入磁盘的情况下很有帮助,但它仍然会说文件格式不正确或由于缺少插件而无法播放文件。

It was something to do with JavaScript (which I'm not much comfortable with) where I had to have all meta data in FormData I guess. I'm not sure why this works. Had searched somewhere and found this which worked.

这与 JavaScript(我不太习惯)有关,我猜我必须在 FormData 中拥有所有元数据。我不确定为什么会这样。已经搜索过某个地方,发现这个有效。

Would be great to know what went wrong above. Would accept any other answer explaining this.

很高兴知道上面出了什么问题。会接受解释这一点的任何其他答案。

class SaveVideo(APIView):
    def post(self, request):
        filename = 'demo.mp4'
        with open(filename, 'wb+') as destination:
            for chunk in request.FILES['video-blob'].chunks():
                destination.write(chunk)
        return Response({"status":"ok"})

Javascript

Javascript

function xhr(url, data, callback) {
      var request = new XMLHttpRequest();
            request.onreadystatechange = function () {
                if (request.readyState == 4 && request.status == 200) {
                   callback(request.responseText);
                }
            };

    request.open('POST', url);
    request.setRequestHeader('X-CSRFToken',Cookies.get('csrftoken'))
    request.send(data);
    }

    var fileType = 'video'; 


    var fileName = 'ABCDEF.webm'; 

    var formData = new FormData();
    formData.append(fileType , fileName);
    formData.append(fileType + '-blob', blob);
    xhr(url,formData,callback_function);

回答by Martin Evans

You could using Python's base64library to encode and decode data in your SaveBlobclass:

您可以使用 Python 的base64库对SaveBlob类中的数据进行编码和解码:

import base64

video_stream = "hello"

with open('file.webm', 'wb') as f_vid:
    f_vid.write(base64.b64encode(video_stream))

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:

还给你原件video_stream

hello

For this simple example, the saved file would appear as:

对于这个简单的例子,保存的文件将显示为:

aGVsbG8=

回答by snakecharmerb

The first argument to struct.packis a format stringthat 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:

的第一个参数struct.pack是一个格式字符串,用于指定结构的布局。您只传递要打包的字节,因此这被解释为无效格式:

>>> 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:

如果只是将数据写入磁盘,则不太可能需要对数据进行*或 base64 编码;只需将字节直接写入文件:

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 base64package as Martin Evans recommends in his answer..

Base64 编码真正用于在传输机制需要 ascii 编码数据时传输二进制数据,因此仅将这种编码应用于写入文件没有任何好处。如果您真的需要对数据进行 base64 编码,请使用 python 的base64包,正如 Martin Evans 在他的回答中所推荐的那样。

*It may be necessary to pack the data if it's being moved between platforms with different endianness.

*如果数据在不同字节序的平台之间移动,则可能需要打包数据。