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