javascriptでblobをアップロードするにはどうすればよいですか?


107

この構造にblobデータがあります。

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

最近のChrome getUerMedia()Recorder.jsを使用して録音された実際のサウンドデータです。

jqueryのpostメソッドを使用して、このblobをサーバーにアップロードするにはどうすればよいですか?私は運なしでこれを試しました:

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

1
このためにbinaryJSの使用を検討する必要があるかもしれません。データをストリーミングしている場合、それでうまくいくかもしれません。
toxicate20

この答えも非常に詳細です。stackoverflow.com/a/8758614/1331430
FABRICIOマット

回答:


123

これを試して

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

あなたは使用する必要がありますいるFormDataのAPIをと設定jQuery.ajaxのをprocessDatacontentTypeしますfalse


1
AJAXなしでこれを行う方法も知っていますか?
William Entriken 2013

@FullDecentどういう意味ですか?File APIを使用してファイルをダウンロードするようにユーザーに要求するには または、BLOBコンテンツを保存するだけですか?
FABRICIOマット

4
基本的に$('input[type=file]').value=blob
William Entriken 2013

14
:セキュリティ要件は、ファイルの入力値のプログラム設定防ぐstackoverflow.com/questions/1696877/...
yeeking

9
Fileとは異なり、Blobはサーバーに送信されるときに一般的なファイル名を持つことに注意してください。しかし、あなたがいるFormDataのBLOBファイル名をspeficyことができます。stackoverflow.com/questions/6664967/...
セバスチャン・ローバー

20

JavaScriptからFormDataa Blobをサーバーに送信するために実際に使用する必要はありません(a 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);

もちろん、従来のHTMLマルチパートフォームを「AJAX」実装に置き換える場合(つまり、バックエンドがマルチパートフォームデータを使用する場合)、FormData別の回答で説明されているようにオブジェクトを使用する必要があります。

ソース:XMLHttpRequest2の新しいトリック| HTML5 Rocks


17

上記の例で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);
?>

関数呼び出しの行をdata: fd,に変更できると確信しています。ajaxdata: blob,
ケニーエビット2014年

11

@yeekingの例が動作するようにするには、FormDataを使用せず、javascriptオブジェクトを使用してblobを転送しました。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);
?>

7
phpファイルの注意-HTTPクライアントがファイル名を設定することを許可すると、悪意のあるコンテンツを選択したファイルおよびディレクトリにアップロードするために使用できます。(Apacheがそこに書き込むことができる限り)
2014

9

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

2

上記のすべての解決策に加えて、関連する回答の解決策も試しました。BLOBを手動でHTMLInputElementのファイルプロパティに渡す、FileReaderのすべてのreadAs *メソッドを呼び出す、FormData.append呼び出しの2番目の引数としてFileインスタンスを使用する、以下を取得して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を介してこの値を増やすことができます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.