Javascript 如何上传一个 blob?

我在这个结构中有一个 blob 数据:

Blob {type: "audio/wav", size: 655404, slice: function}
size: 655404
type: "audio/wav"
__proto__: Blob

它实际上是使用最近的 ChromegetUerMedia()唱片公司录制的声音数据

如何使用 jquery 的 post 方法将这个 blob 上传到服务器:

   $.post('http://localhost/upload.php', { fname: "test.wav", data: soundBlob },
function(responseText) {
console.log(responseText);
});
221241 次浏览

你可以使用 表单数据 API

如果使用 jquery.ajax,则需要设置 processData: falsecontentType: false

var fd = new FormData();
fd.append('fname', 'test.wav');
fd.append('data', soundBlob);
$.ajax({
type: 'POST',
url: '/upload.php',
data: fd,
processData: false,
contentType: false
}).done(function(data) {
console.log(data);
});

我无法使用上面的示例来处理 blob,我想知道 upload.php 中到底有什么。给你:

(仅在 Chrome28.0.1500.95中测试)

// javascript function that uploads a blob to upload.php
function uploadBlob(){
// create a blob here for testing
var blob = new Blob(["i am a blob"]);
//var blob = yourAudioBlobCapturedFromWebAudioAPI;// for example
var reader = new FileReader();
// this function is triggered once a call to readAsDataURL returns
reader.onload = function(event){
var fd = new FormData();
fd.append('fname', 'test.txt');
fd.append('data', event.target.result);
$.ajax({
type: 'POST',
url: 'upload.php',
data: fd,
processData: false,
contentType: false
}).done(function(data) {
// print the output from the upload.php script
console.log(data);
});
};
// trigger the read from the reader...
reader.readAsDataURL(blob);


}

Php 的内容:

<?
// pull the raw binary data from the POST array
$data = substr($_POST['data'], strpos($_POST['data'], ",") + 1);
// decode it
$decodedData = base64_decode($data);
// print out the raw data,
echo ($decodedData);
$filename = "test.txt";
// write the data out to the file
$fp = fopen($filename, 'wb');
fwrite($fp, $decodedData);
fclose($fp);
?>

我可以通过不使用 FormData 而使用 javascript 对象来传输 blob 来获得@yeeking 示例。使用一个使用 record der.js 创建的声音块工作。在 Chrome 版本32.0.1700.107中测试

function uploadAudio( blob ) {
var reader = new FileReader();
reader.onload = function(event){
var fd = {};
fd["fname"] = "test.wav";
fd["data"] = event.target.result;
$.ajax({
type: 'POST',
url: 'upload.php',
data: fd,
dataType: 'text'
}).done(function(data) {
console.log(data);
});
};
reader.readAsDataURL(blob);
}

Upload.php 的内容

<?
// pull the raw binary data from the POST array
$data = substr($_POST['data'], strpos($_POST['data'], ",") + 1);
// decode it
$decodedData = base64_decode($data);
// print out the raw data,
$filename = $_POST['fname'];
echo $filename;
// write the data out to the file
$fp = fopen($filename, 'wb');
fwrite($fp, $decodedData);
fclose($fp);
?>

实际上,您不必使用 FormData从 JavaScript 向服务器发送 Blob(而且 File也是 Blob)。

JQuery 示例:

var file = $('#fileInput').get(0).files.item(0); // instance of File
$.ajax({
type: 'POST',
url: 'upload.php',
data: file,
contentType: 'application/my-binary-type', // set accordingly
processData: false
});

香草 JavaScript 示例:

var file = $('#fileInput').get(0).files.item(0); // instance of File
var xhr = new XMLHttpRequest();
xhr.open('POST', '/upload.php', true);
xhr.onload = function(e) { ... };
xhr.send(file);

当然,如果要用“ AJAX”实现替换传统的 HTML 多部分表单(即后端使用多部分表单数据) ,则需要使用另一个答案中描述的 FormData对象。

资料来源: XMLHttpRequest2 | HTML5 Rocks 中的新技巧

我尝试了以上所有的解决方案,除此之外,那些在相关的答案。解决方案包括但不限于手动将 blob 传递给 HTMLInputElement 的 File 属性,调用 FileReader 上的所有 readAs * 方法,使用 File 实例作为 FormData.append 调用的第二个参数,尝试通过获取 URL.createObjectURL (myBlob)上的值来获取 blob 数据作为字符串,结果非常糟糕,导致我的机器崩溃。

现在,如果您碰巧尝试了这些或更多,但仍然发现无法上传您的 blob,这可能意味着问题出在服务器端。在我的例子中,blob 超过了 PHP.INI 中的 http://www.php.net/manual/en/ini.core.php#ini.upload-max-filesize和 post _ max _ size 限制,因此文件离开了前端表单,但是被服务器拒绝了。您可以直接在 PHP.INI 中增加这个值,也可以通过。Htaccess

2019年最新情况

这将使用最新的 获取 API更新答案,并且不需要 jQuery。

免责声明: 不适用于 IE,Opera Mini 和旧版浏览器。参见 犬科动物

基本获取

它可以很简单:

  fetch(`https://example.com/upload.php`, {method:"POST", body:blobData})
.then(response => console.log(response.text()))

带错误处理的抓取

在添加错误处理之后,它可能看起来像:

fetch(`https://example.com/upload.php`, {method:"POST", body:blobData})
.then(response => {
if (response.ok) return response;
else throw Error(`Server returned ${response.status}: ${response.statusText}`)
})
.then(response => console.log(response.text()))
.catch(err => {
alert(err);
});

PHP 代码

这是 upload.php 中的服务器端代码。

<?php
// gets entire POST body
$data = file_get_contents('php://input');
// write the data out to the file
$fp = fopen("path/to/file", "wb");


fwrite($fp, $data);
fclose($fp);
?>