Як Javascript може завантажити завантаження крапки?


107

У цій структурі є дані про краплі:

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

Це фактично звукові дані, записані за допомогою останніх Chrome getUerMedia()і Recorder.js

Як я можу завантажити цю крапку на сервер, використовуючи метод публікації jquery? Я спробував це без жодної удачі:

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

1
Ви можете подумати про використання binaryJS для цього. Якщо ви передаєте дані, це може зробити трюк.
токсикант20

Ця відповідь також дуже детальна. stackoverflow.com/a/8758614/1331430
Fabrício Матовий

Відповіді:


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

Вам потрібно використовувати API FormData та встановити jQuery.ajax's processDataі contentTypeto false.


1
Чи знаєте ви, як це зробити і без AJAX?
Вільям Ентрікен

@FullDecent Що ти маєш на увазі? Запропонувати користувачу завантажити файл за допомогою API API? Або просто зберігати вміст краплі?
Fabrício Matté

4
Робити в основному$('input[type=file]').value=blob
Вільям Ентрікен

14
Вимоги безпеки запобігають програмні установки значень вхідних файлів: stackoverflow.com/questions/1696877 / ...
yeeking

9
Зауважте, що Blob має загальне ім'я файлу при надсиланні на сервер, на відміну від File. Але ви можете speficy ім'я файлу Blob в FormData: stackoverflow.com/questions/6664967 / ...
Себастьєн Лорбер

20

Насправді вам не потрібно використовувати FormDataдля надсилання Blobсервера з JavaScript (а 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


17

Я не міг отримати вищенаведений приклад для роботи з краплями, і хотів дізнатися, що саме є у 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,у ajaxвиклику функції на data: blob,.
Кенні Евітт

11

Мені вдалося змусити @yeeking приклад працювати, не використовуючи FormData, але використовуючи об’єкт javascript для передачі краплі. Працює з звуковим блохом, створеним за допомогою recorder.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);
?>

7
Обережно у файлі php - якщо ви дозволите HTTP-клієнту встановити ім'я файлу, вони можуть використовувати його для завантаження шкідливого вмісту у вибраний файл та каталог. (доки Apache може писати там)
вигукуючи

9

Оновлення 2019 року

Це оновлення відповідей за допомогою останнього API Fetch і не потребує 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);
?>

2

Я спробував усі рішення вище, а крім того, і відповідні відповіді. Рішення, включаючи, але не обмежуючись, передачу крапки вручну до властивості файлу HTMLInputElement, виклик усіх методів readAs * у FileReader, використання екземпляра File як другого аргументу для виклику FormData.append, намагаючись отримати дані крапки у вигляді рядка шляхом отримання значення в URL.createObjectURL (myBlob), що виявилося неприємним і розбило мою машину.

Тепер, якщо у вас трапляються спроби тих чи більше, і ви все ще виявите, що не можете завантажити свою крапку, це може означати, що проблема стоїть на сервері. У моєму випадку моя крапка перевищила http://www.php.net/manual/en/ini.core.php#ini.upload-max-filesize та post_max_size межа в PHP.INI, тому файл залишає передню частину форми, але сервер відхилений. Ви можете або збільшити це значення безпосередньо в PHP.INI, або через .htaccess

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.