【问题标题】:How can javascript upload a blob?javascript如何上传blob?
【发布时间】:2012-10-31 06:23:56
【问题描述】:

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

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

其实是用最近的ChromegetUerMedia()Recorder.js录制的声音数据

如何使用 jquery 的 post 方法将此 blob 上传到服务器?我试过这个没有任何运气:

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

【问题讨论】:

标签: javascript jquery html


【解决方案1】:

您可以使用FormData 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);
});

【讨论】:

  • 你知道如何在没有 AJAX 的情况下做到这一点吗?
  • @FullDecent 你是什么意思?提示用户使用 File API 下载文件?还是只存储 blob 内容?
  • 基本做$('input[type=file]').value=blob
  • 安全要求阻止对文件输入值进行编程设置:stackoverflow.com/questions/1696877/…
  • 请注意,与 File 不同,Blob 在发送到服务器时具有通用文件名。但您可以在 FormData 中指定 Blob 文件名:stackoverflow.com/questions/6664967/…
【解决方案2】:

我无法让上面的示例与 blob 一起使用,我想知道 upload.php 中的确切内容。所以给你:

(仅在 Chrome 28.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);

}

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, 
echo ($decodedData);
$filename = "test.txt";
// write the data out to the file
$fp = fopen($filename, 'wb');
fwrite($fp, $decodedData);
fclose($fp);
?>

【讨论】:

  • 我很确定您可以将ajax 函数调用中的data: fd, 行更改为data: blob,
【解决方案3】:

我能够通过不使用 FormData 而是使用 javascript 对象来传输 blob 来让 @yeeking 示例工作。适用于使用 recorder.js 创建的声音 blob。在 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);
?>

【讨论】:

  • 小心 php 文件 - 如果您允许 HTTP 客户端设置文件名,他们可以使用它将恶意内容上传到他们选择的文件和目录中。 (只要 Apache 可以写在那里)
【解决方案4】:

实际上,您不必使用 FormData 从 JavaScript 向服务器发送 BlobFile 也是 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 对象。

来源:New Tricks in XMLHttpRequest2 | HTML5 Rocks

【讨论】:

    【解决方案5】:

    我尝试了上述所有解决方案,此外还尝试了相关答案中的解决方案。解决方案包括但不限于手动将 blob 传递给 HTMLInputElement 的文件属性,调用 FileReader 上的所有 readAs* 方法,使用 File 实例作为 FormData.append 调用的第二个参数,尝试通过获取将 blob 数据作为字符串获取URL.createObjectURL(myBlob) 中的值变得很糟糕并导致我的机器崩溃。

    现在,如果您碰巧尝试了这些或更多尝试,但仍然无法上传您的 Blob,则可能意味着问题出在服务器端。就我而言,我的 blob 超出了 PHP.INI 中的 http://www.php.net/manual/en/ini.core.php#ini.upload-max-filesize 和 post_max_size 限制,因此该文件离开了前端表单但被服务器拒绝了。您可以直接在 PHP.INI 中或通过 .htaccess

    增加此值

    【讨论】:

      【解决方案6】:

      2019 年更新

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

      免责声明:不适用于 IE、Opera Mini 和旧版浏览器。见caniuse

      基本提取

      可以这么简单:

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

      【讨论】:

      • 最佳答案使用 jquery,甚至比这里的错误处理版本更复杂。它有126票。另一方面,这有 11 票(现在是 12 票)并且本机与 js 一起使用并且非常短。我希望我有 120 票可以将这个解决方案放在它所属的地方。
      • @StephenDuffy 答案相隔 2 年
      猜你喜欢
      • 2015-01-02
      • 2018-07-16
      • 2013-08-17
      • 2019-03-10
      • 2020-01-18
      • 1970-01-01
      • 2019-09-29
      • 1970-01-01
      • 2012-12-28
      相关资源
      最近更新 更多