【问题标题】:Saving a blob to a file in python在python中将blob保存到文件中
【发布时间】:2022-05-19 22:06:56
【问题描述】:

我正在尝试将通过 ajax 发送的 blob 保存为 python 中的文件。之前经历过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()

结果为@​​987654323@

只需使用此vid.write(video_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;
}

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

【问题讨论】:

    标签: javascript python


    【解决方案1】:

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

    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)
    

    还你原来的video_stream

    hello
    

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

    aGVsbG8=
    

    【讨论】:

      【解决方案2】:

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

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

      构造一个有效的格式字符串可以解决这个问题(但请注意,您需要根据您的数据和平台构造格式字符串):

      >> n = len(bs)    # 3
      >>> fmt = '{:d}s'.format(n)    # '3s'
      >>> struct.pack(fmt, bs)
      b'\x01VV'
      

      如果只是将数据写入磁盘,则不太可能需要打包* 或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()
      

      您的视频播放器应该能够读取二进制文件并正确解释它。

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

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

      【讨论】:

      • 感谢您让我了解 struct.pack 背后的详细信息
      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 2018-04-20
        • 2020-02-11
        • 1970-01-01
        • 1970-01-01
        • 2021-12-22
        • 1970-01-01
        • 2020-08-25
        • 2015-12-07
        • 2021-07-10
        相关资源
        最近更新 更多