使用 POST 表单发送 Blob 对象

Posted

技术标签:

【中文标题】使用 POST 表单发送 Blob 对象【英文标题】:Send Blob object with POST Form 【发布时间】:2018-05-03 14:25:34 【问题描述】:

我从麦克风录制音频,我需要使用 POST 表单将其发送到服务器。

我可以录制并拥有 blob 对象,但我不知道如何发送。 我试图将 blob 转换为 ArrayBuffer 并使用该值设置一个隐藏字段,但我不确定它是否是正确的方法。

这是获取blob,转换为ArrayBuffer并设置为隐藏字段的js代码:

var arrayBuffer;
var fileReader = new FileReader();
fileReader.onload = function(event) 
    arrayBuffer = event.target.result;

    jQuery('hidden_field').val(arrayBuffer);
;
fileReader.readAsArrayBuffer(blobObject);

之后,我只需使用提交按钮正常发送表单。 在服务器上,如果我对请求对象执行 dd 命令,这就是我得到的:

array:2 [▼
    "_token" => "8HcKsoGblW9lEPVY0JYrFDbDAajdb63xdSQC3r5E"
    "hidden_field" => "[object ArrayBuffer]"
]

不知道对不对。 如果正确,我该如何处理?

更新 我解决了将隐藏字段中的 blob 作为 base64 字符串发送的问题,使用以下代码:

var fileReader = new FileReader();
fileReader.onload = function(event) 
     jQuery('#hidden').val(fileReader.result.substr(fileReader.result.indexOf(',')+1));
;
fileReader.readAsDataURL(s);

【问题讨论】:

相关:***.com/questions/37218585/… 【参考方案1】:

您可以将其读取为 dataURI 并使用 base64 字符串分配 hidden_​​field 并稍后在后端对其进行解码...

否则这是将 blob 附加到表单的唯一方法

// only way to change input[type=file] value is with a other FileList instance
// and this is currently the only way to construct a new FileList
function createFileList(a) 
  a = [].slice.call(Array.isArray(a) ? a : arguments)
  for (var c, b = c = a.length, d = !0; b-- && d;) d = a[b] instanceof File
  if (!d) throw new TypeError('expected argument to FileList is File or array of File objects')
  for (b = (new ClipboardEvent('')).clipboardData || new DataTransfer; c--;) b.items.add(a[c])
  return b.files


var file = new File([blobObject], 'filename.txt', type: 'text/plain')
var input = document.createElement('input')

input.type = 'file'
// input.multiple = true
input.files = createFileList(file)
input.name = 'hidden_field'
input.hidden = true

form.appendChild(input)

这不适用于每个浏览器,因为所有浏览器都有限制,我确定 firefox 和 blink 支持此功能尚未测试其他浏览器

另一种解决方案是使用ajax + FormData进行请求

var form = document.querySelector('form')

// get all other field in the form
var fd = new FormData(form)
// or start of with a empty form
var fd = new FormData()

// append the needed blob to the formdata
fd.append('hidden_field', blobObject, 'filename.txt')

fetch(form.action, 
  method: form.method,
  body: fd
).then(function(res) 
  if (!res.ok) 
    console.log('something unexpected happened')
  
  res.text().then(function(text) 
    // navigate to forms action page
    // location.href = form.action
  )
)

这有更多的跨浏览器支持

【讨论】:

以上是关于使用 POST 表单发送 Blob 对象的主要内容,如果未能解决你的问题,请参考以下文章

axios发送post请求,如何提交表单数据?

表单对象的提交方法由啥属性设定?

如何在 Vuex 中通过 POST 请求发送状态数据?

将状态对象作为POST主体发送并在Express服务器中按未定义的方式接收它

从表单收集数据,在对象中堆叠并使用 Vue 使用 AJAX 发送

表单在 2 次 ajax 更新后无法发送 POST 请求