web-dev-qa-db-fra.com

Comment javascript peut-il télécharger un blob?

J'ai une donnée blob dans cette structure:

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

Il s’agit en fait de données audio enregistrées à l’aide des récents Chrome getUerMedia() et Recorder.js

Comment puis-je télécharger ce blob sur le serveur en utilisant la méthode post de jquery? J'ai essayé sans aucune chance:

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

Essaye ça

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

Vous devez utiliser FormData API et définir le jQuery.ajax _ processData et contentType à false.

104
Fabrício Matté

Je ne pouvais pas obtenir que l'exemple ci-dessus fonctionne avec des blobs et je voulais savoir ce qui se trouve exactement dans upload.php. Alors voilà:

(testé uniquement dans 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);

}

Le contenu de 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);
?>
16
yeeking

En fait, vous n'avez pas besoin d'utiliser FormData pour envoyer un Blob au serveur à partir de JavaScript (et un File est également un Blob).

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

Exemple JavaScript vanille:

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

Si vous remplacez un formulaire multipart HTML traditionnel par une implémentation "AJAX" (c’est-à-dire que votre back-end consomme des données de formulaire multipart), vous souhaitez utiliser l’objet FormData comme décrit dans une autre réponse.

Source: Nouvelles astuces dans XMLHttpRequest2 | HTML5 Rocks

14
Dmitry Pashkevich

J'ai pu obtenir que l'exemple de @yeeking fonctionne en n'utilisant pas FormData, mais en utilisant un objet javascript pour transférer le blob. Fonctionne avec une goutte de son créée à l'aide de recorder.js. Testé dans Chrome version 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);
}

Contenu de 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);
?>
11
Soumen Basak

Mise à jour 2019

Ceci met à jour les réponses avec le dernier Fetch API et n'a pas besoin de jQuery.

Disclaimer: ne fonctionne pas sur IE, Opera Mini et anciens navigateurs. Voir caniuse .

Fetch de base

Cela pourrait être aussi simple que:

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

Récupération avec gestion des erreurs

Après avoir ajouté le traitement des erreurs, cela pourrait ressembler à:

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

Code PHP

C'est le code côté serveur dans 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
chatnoir

J'ai essayé toutes les solutions ci-dessus et, en plus, celles des réponses associées. Solutions comprenant, entre autres, le transfert manuel de l'objet blob vers une propriété de fichier HTMLInputElement, appelant toutes les méthodes readAs * sur FileReader, en utilisant une instance File comme second argument d'un appel FormData.append, en essayant d'obtenir les données d'objet blob sous forme de chaîne en obtenant les valeurs de URL.createObjectURL (myBlob) qui se sont avérées méchantes et ont écrasé ma machine.

Maintenant, si vous tentez ces tentatives ou plus et que vous ne parvenez toujours pas à télécharger votre objet blob, cela peut signifier que le problème se situe côté serveur. Dans mon cas, mon blob a dépassé la limite http://www.php.net/manual/en/ini.core.php#ini.upload-max-filesize et la limite post_max_size dans PHP.INI donc le fichier quittait le formulaire frontal mais était rejeté par le serveur. Vous pouvez soit augmenter cette valeur directement dans PHP.INI ou via .htaccess

1
I Want Answers