Сохранить в локальный файл из Blob

У меня к вам сложный вопрос, над которым я бьюсь уже некоторое время.

Я ищу решение, где я могу сохранить файл на компьютер пользователя, без локального хранилища, потому что локальное хранилище имеет ограничение 5 МБ. Я хочу "Сохранить в файл" -dialog, но данные, которые я хочу сохранить, доступны только в javascript, и я хотел бы запретить отправку данных обратно на сервер, а затем отправить их снова.

Сценарий использования заключается в том, что служба, над которой я работаю, сохраняет сжатые и зашифрованные фрагменты данных пользователей, поэтому сервер не знает, что находится в этих фрагментах, и при отправке данных обратно на сервер это вызовет 4-кратный трафик и сервер получает незашифрованные данные, что делает все шифрование бесполезным.

Я нашел функцию javascript для сохранения данных на компьютер пользователя с помощью "Сохранить в файл" -dialog, но работа над этим была прекращена и не полностью поддерживается. Вот это: http://www.w3.org/TR/file-writer-api/

Так как у меня нет window.saveAs, как можно сохранить данные из объекта Blob, не отправляя все на сервер?

Было бы здорово, если бы я мог получить подсказку, что искать.

Я знаю, что это работает, потому что MEGA делает это, но я хочу свое собственное решение :)

Ответ 1

Ваш лучший вариант - использовать URL-адрес blob (который является специальным URL-адресом, указывающим на объект в памяти браузера):

var myBlob = ...;
var blobUrl = URL.createObjectURL(myBlob);

Теперь у вас есть выбор, чтобы просто перенаправить на этот url (window.location.replace(blobUrl)) или создать ссылку на него. Второе решение позволяет указать имя файла по умолчанию:

var link = document.createElement("a"); // Or maybe get it from the current document
link.href = blobUrl;
link.download = "aDefaultFileName.txt";
link.innerHTML = "Click here to download the file";
document.body.appendChild(link); // Or append it whereever you want

Ответ 2

FileSaver.js реализует saveAs для определенных браузеров, у которых его нет

https://github.com/eligrey/FileSaver.js

Протестировано с FileSaver.js 1.3.8, протестировано на Chromium 75 и Firefox 68, ни один из которых не имеет saveAs.

Принцип работы, по-видимому, заключается в том, чтобы просто создать элемент <a и щелкнуть по нему с помощью JavaScript о ужасах Интернета.

Вот демонстрация, которая сохраняет BLOB-объект, созданный с помощью canvas.toBlob, в папку загрузки с выбранным именем mypng.png:

var canvas = document.getElementById("my-canvas");
var ctx = canvas.getContext("2d");
var pixel_size = 1;

function draw() {
    console.log("draw");
    for (x = 0; x < canvas.width; x += pixel_size) {
        for (y = 0; y < canvas.height; y += pixel_size) {
            var b = 0.5;
            ctx.fillStyle =
                "rgba(" +
                (x / canvas.width) * 255 + "," +
                (y / canvas.height) * 255 + "," +
                b * 255 +
                ",255)"
            ;
            ctx.fillRect(x, y, pixel_size, pixel_size);
        }
    }
    canvas.toBlob(function(blob) {
      saveAs(blob, 'mypng.png');
    });
}
window.requestAnimationFrame(draw);
<canvas id="my-canvas" width="512" height="512" style="border:1px solid black;"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.min.js"></script>

Ответ 3

Из файла picker или input type = выбор файла файла сохраните имя файла в локальном хранилище:

HTML:

<audio id="player1">Your browser does not support the audio element</audio>

JavaScript:

function picksinglefile() {
    var fop = new Windows.Storage.Pickers.FileOpenPicker();
    fop.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.musicLibrary;
    fop.fileTypeFilter.replaceAll([".mp3", ".wav"]);
    fop.pickSingleFileAsync().then(function (file) {
        if (file) {
            // save the file name to local storage
            localStorage.setItem("alarmname$", file.name.toString());
        } else {
            alert("Operation Cancelled");
        }
    });
}

Затем в вашем коде, когда вы хотите воспроизвести выбранный вами файл, используйте следующее, которое получает файл, используя только его имя из музыкальной библиотеки. (В манифесте UWP-пакета установите "Capabilites" для включения "Музыкальной библиотеки".)

        var l = Windows.Storage.KnownFolders.musicLibrary;
        var f = localStorage.getItem("alarmname$").toString(); // retrieve file by name
        l.getFileAsync(f).then(function (file) {
            // storagefile file is available, create URL from it
            var s = window.URL.createObjectURL(file);
            var x = document.getElementById("player1");
            x.setAttribute("src", s);
            x.play();
        });