Javascript 在python中将blob保存到文件

Javascript 在python中将blob保存到文件,javascript,python,Javascript,Python,我试图将通过ajax发送的blob保存为python中的文件。我以前也经历过这种情况 它导致错误:结构格式中的错误字符 只需使用这个vid.write(video\u stream.decode('base64')) 不使用struct.pack保存文件,但当我打开视频时,它导致无法确定流的类型 ajax调用是这样的,但我想它看起来不错 function call_ajax(request_type,request_url,request_data) { var data_vid =

我试图将通过ajax发送的blob保存为python中的文件。我以前也经历过这种情况

它导致
错误:结构格式中的错误字符

只需使用这个
vid.write(video\u stream.decode('base64'))
不使用
struct.pack
保存文件,但当我打开视频时,它导致无法确定流的类型

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;
}
任何帮助都将不胜感激。欢迎对任何缺陷或可能原因提出任何建议

您可以使用Python库对
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
将原始的
视频流返回给您

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

aGVsbG8=

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
如果数据刚刚写入磁盘,则不太可能需要对其进行打包*或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()
您的视频播放器应该能够读取二进制文件并正确解释它

当传输机制需要ascii编码的数据时,Base64编码实际上用于传输二进制数据,因此仅将此编码应用于写入文件没有任何好处。如果您确实需要对数据进行base64编码,请使用Martin Evans在回答中建议的python包


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

其他解决方案很有用,它会将文件写入磁盘,但可能会说文件格式不正确或由于缺少插件而无法播放文件

这与JavaScript有关(我不太习惯使用JavaScript),我想我必须将所有元数据都放在FormData中。我不知道为什么会这样。我找了个地方,找到了这个

如果能知道上面出了什么问题,那就太好了。我会接受任何其他解释这一点的答案

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

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);

感谢您让我了解struct.pack背后的详细信息
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"})
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);