Использование HTML5 / Javascript для генерации и сохранения файла

274

В последнее время я возился с WebGL и получил работу читателя Collada. Проблема в том, что она довольно медленная (Collada - очень подробный формат), поэтому я собираюсь начать конвертирование файлов в более простой в использовании формат (возможно, JSON). Дело в том, что у меня уже есть код для анализа файла в Javascript, поэтому я также могу использовать его в качестве моего экспортера! Проблема заключается в сохранении.

Теперь я знаю, что могу разобрать файл, отправить результат на сервер и попросить браузер запросить файл с сервера в качестве загрузки. Но на самом деле сервер не имеет никакого отношения к этому конкретному процессу, поэтому зачем его привлекать? У меня уже есть содержимое нужного файла в памяти. Есть ли способ, которым я мог бы представить пользователю загрузку с использованием чистого javascript? (Я сомневаюсь, но могу также спросить...)

И чтобы быть ясным: я не пытаюсь получить доступ к файловой системе без знаний пользователей! Пользователь предоставит файл (возможно, с помощью перетаскивания), script преобразует файл в память, и пользователю будет предложено загрузить результат. Все из которых должны быть "безопасными" действиями в отношении браузера.

[EDIT]: Я не упоминал об этом заранее, поэтому плакаты, которые ответили "Flash", достаточно действительны, но часть того, что я делаю, - это попытка подчеркнуть, что может быть сделано с чистым HTML5... так что Flash в моем случае. (Хотя это абсолютно правильный ответ для любого, кто делает "настоящее" веб-приложение.) В таком случае мне кажется, что мне не повезло, если я не хочу привлекать сервер. В любом случае, спасибо!

  • 8
    Вы могли бы рассмотреть вопрос об изменении принятого ответа, похоже, теперь существует чисто HTML-способ
Теги:
download

14 ответов

246
Лучший ответ

ОК, создавая данные: URI определенно делает трюк для меня, благодаря Мэтью и Деннкстеру, указывающим на этот вариант! Вот в основном, как я это делаю:

1) получить все содержимое в строку под названием "контент" (например, создав ее там изначально или путем чтения innerHTML тега уже построенной страницы).

2) Создайте URI данных:

uriContent = "data:application/octet-stream," + encodeURIComponent(content);

Будут ограничения длины в зависимости от типа браузера и т.д., но, например, Firefox 3.6.12 работает до 256K. Кодирование в Base64 вместо использования encodeURIComponent может сделать вещи более эффективными, но для меня это нормально.

3) откройте новое окно и переадресовывайте его в этот URI, чтобы указать местоположение загрузки моей страницы, сгенерированной JavaScript:

newWindow = window.open(uriContent, 'neuesDokument');

Что это.

  • 33
    Если вы хотите избежать использования всплывающего окна, которое может быть заблокировано, вы можете установить для location.href содержимое. location.href = uriContent .
  • 12
    Привет, я попробовал это, но он загружает файл как файл .part. Как я могу установить тип файла?
Показать ещё 12 комментариев
234

Простое решение для готовых браузеров HTML5...

function download(filename, text) {
    var pom = document.createElement('a');
    pom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
    pom.setAttribute('download', filename);

    if (document.createEvent) {
        var event = document.createEvent('MouseEvents');
        event.initEvent('click', true, true);
        pom.dispatchEvent(event);
    }
    else {
        pom.click();
    }
}

Использование

download('test.txt', 'Hello world!');
  • 2
    Если вы знаете исходный URL, который хотите скачать, это лучшее решение!
  • 29
    Возможность установить имя файла делает его победителем.
Показать ещё 20 комментариев
79

HTML5 определил метод window.saveAs(blob, filename). Он не поддерживается ни одним браузером прямо сейчас. Но есть библиотека совместимости, называемая FileSaver.js, которая добавляет эту функцию в большинство современных браузеров (включая Internet Explorer 10+). Internet Explorer 10 поддерживает метод navigator.msSaveBlob(blob, filename) (MSDN), который используется в FileSaver.js для поддержки Internet Explorer.

Я написал сообщение с более подробной информацией об этой проблеме.

  • 1
    Как насчет блокировки всплывающих окон? Поведение этой библиотеки похоже на решение @ Nøk. Обычный текст в Firefox открывается по-новому. Только Chrome пытается сохранить его, но он меняет расширение (мне нужен точечный файл без расширения).
  • 1
    @ciembor (объектный URL +) вариант атрибута загрузки (который я использую с Chrome) позволяет вам задать имя файла. У меня это работает в хроме.
Показать ещё 13 комментариев
34

Сохранение больших файлов

Длинные URI данных могут приводить к проблемам с производительностью в браузерах. Другой вариант сохранения созданных на стороне клиента файлов состоит в том, чтобы поместить их содержимое в объект Blob (или File) и создать ссылку для загрузки, используя URL.createObjectURL(blob). Это возвращает URL-адрес, который можно использовать для извлечения содержимого блоба. URL.revokeObjectURL() хранится внутри браузера, пока не будет URL.revokeObjectURL() в URL-адресе, или созданный документ закрыт. Большинство веб-браузеров поддерживают URL-адреса объектов, Opera Mini - единственная, которая их не поддерживает.

Принуждение загрузки

Если данные представляют собой текст или изображение, браузер может открыть файл, а не сохранять его на диск. Чтобы заставить файл загружаться при нажатии ссылки, вы можете использовать атрибут download. Однако не все веб-браузеры поддерживают атрибут загрузки. Другой вариант - использовать application/octet-stream в качестве файла mime-type, но это приводит к тому, что файл представляется как двоичный blob, который особенно непригоден для пользователя, если вы не укажете или не можете указать имя файла. См. Также " Сила, чтобы открыть" Сохранить как... "всплывающее окно в текстовой ссылке нажмите для pdf в HTML ".

Указание имени файла

Если blob создается с помощью конструктора файлов, вы также можете указать имя файла, но только для нескольких браузеров (включая Chrome и Firefox) есть поддержка конструктора файлов. Имя файла также может быть указано как аргумент атрибута download, но это зависит от тонны соображений безопасности. Internet Explorer 10 и 11 предоставляет свой собственный метод msSaveBlob, чтобы указать имя файла.

Пример кода

var file;
var data = [];
data.push("This is a test\n");
data.push("Of creating a file\n");
data.push("In a browser\n");
var properties = {type: 'text/plain'}; // Specify the file mime-type.
try {
  // Specify the filename using the File constructor, but ...
  file = new File(data, "file.txt", properties);
} catch (e) {
  // ... fall back to the Blob constructor if that isn't supported.
  file = new Blob(data, properties);
}
var url = URL.createObjectURL(file);
document.getElementById('link').href = url;
<a id="link" target="_blank" download="file.txt">Download</a>
  • 0
    Могу ли я показать диалоговое окно (всплывающее окно), чтобы указать папку (каталог) для сохранения файла?
  • 0
    @Calvin: я обновил ответ, чтобы объяснить, как форсировать загрузку, и указать имя файла. Я полагаю, что для IE вы можете использовать msSaveBlob чтобы открыть диалоговое окно «Сохранить как». Для других браузеров единственный вариант - вручную выбрать «Сохранить как» в контекстном меню ссылки на скачивание.
Показать ещё 4 комментария
31
function download(content, filename, contentType)
{
    if(!contentType) contentType = 'application/octet-stream';
        var a = document.createElement('a');
        var blob = new Blob([content], {'type':contentType});
        a.href = window.URL.createObjectURL(blob);
        a.download = filename;
        a.click();
}
  • 3
    Какое влияние оказывает contentType? Для чего его используют?
  • 3
    Этот отлично работает даже в последнем Chrome, в отличие от ответа @ Matěj Pokorný. Благодарю.
Показать ещё 2 комментария
27

Взгляните на Doug Neiner Downloadify, который является интерфейсом JavaScript на основе Flash для этого.

Downloadify - это небольшая библиотека JavaScript + Flash, которая позволяет генерировать и сохранять файлы "на лету" в браузере без взаимодействия с сервером.

  • 6
    Для большинства людей это, вероятно, ответ, который им понадобится. Поэтому, даже если он не соответствует моим конкретным требованиям (как описано выше), я отмечаю его как принятый ответ.
  • 2
    @ Тодзи ах, понятно. Может быть, переспросить и перефразировать под баннером HTML 5 и пометить соответственно? Это, вероятно, привлечет тех пользователей, которые знают об этой конкретной области (я полагаю, все еще сравнительно небольшая толпа сейчас). Я почти уверен, что это можно сделать в HTML 5, но я понятия не имею, как.
Показать ещё 13 комментариев
14

Простое решение!

<a download="My-FileName.txt" href="data:application/octet-stream,HELLO-WORLDDDDDDDD">Click here</a>    

Работает во всех современных браузерах (см. DEMO).

p.s. href можно также установить с помощью Javascript:
'data:application/octet-stream,' + encodeURIComponent(content);

  • 0
    Привет, вы знаете, как задать поведение атрибута «скачать», используя window.open или другую функцию javascript?
  • 1
    @yucer У window.open() нет атрибута загрузки (или какого-либо другого атрибута window.open() . Это не имеет значения. Вы можете использовать этот метод и .click() к нему .click() , но посмотрите время, так как Firefox не понравится, если вы .click() прежде чем позволить элементу присоединиться к телу.
Показать ещё 2 комментария
10

Вы можете сгенерировать URI данных. Однако существуют ограничения, зависящие от браузера.

  • 1
    Это интересно. Я посмотрю на это больше, когда у меня будет шанс. Спасибо!
  • 0
    мне было бы интересно посмотреть, если этот подход работает
Показать ещё 5 комментариев
9

Я использовал FileSaver (https://github.com/eligrey/FileSaver.js), и он отлично работает.
Например, я сделал эту функцию для экспорта журналов, отображаемых на странице.
Вы должны передать массив для instanciation Blob, так что я просто, возможно, не написал это правильно, но он работает для меня.
На всякий случай, будьте осторожны с заменой: это синтаксис, чтобы сделать это глобальным, иначе он заменит только первый, который он встретит.

exportLogs : function(){
    var array = new Array();

    var str = $('#logs').html();
    array[0] = str.replace(/<br>/g, '\n\t');

    var blob = new Blob(array, {type: "text/plain;charset=utf-8"});
    saveAs(blob, "example.log");
}
  • 2
    FileSaver хорош, вот IE Shim для функции до IE10 preIE10SaveAs: (имя файла, filecontent, mimetype) {var w = window.open (); var doc = w.document; doc.open (mimetype, 'replace'); doc.charset = "utf-8"; doc.write (filecontent); doc.close (); doc.execCommand («Сохранить как», null, имя файла); }
  • 0
    Не работает хорошо в Safari.
Показать ещё 2 комментария
8

Я нашел два простых подхода, которые работают для меня. Сначала, используя уже нажатый элемент a и вводя данные загрузки. А во-вторых, генерируем элемент a с данными загрузки, выполняя a.click() и удаляя его снова. Но второй подход работает только при вызове действия щелчка пользователя. (Некоторые) Браузерный блок click() из других контекстов, например, при загрузке или срабатывании после таймаута (setTimeout).

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="UTF-8">
    <script type="text/javascript">
      function linkDownload(a, filename, content) {
        contentType =  'data:application/octet-stream,';
        uriContent = contentType + encodeURIComponent(content);
        a.setAttribute('href', uriContent);
        a.setAttribute('download', filename);
      }
      function download(filename, content) {
        var a = document.createElement('a');
        linkDownload(a, filename, content);
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
      }
    </script>
   </head>
  <body>
    <a href="#" onclick="linkDownload(this, 'test.txt', 'Hello World!');">download</a>
    <button onclick="download('test.txt', 'Hello World!');">download</button>
  </body>
</html>
  • 2
    Вы также можете вставить a в документ (возможно, с помощью "display:none" ), щелкнуть по нему, а затем удалить его.
  • 1
    будет ли это работать в браузерах, где атрибут загрузки не поддерживается, как даже современный ie и safari .. caniuse.com/#feat=download
Показать ещё 2 комментария
6

Вот ссылка на метод URI данных, предложенный Мэтью, он работал на сафари, но не очень хорошо, потому что я не мог установить тип файла, он становится сохраненным как "неизвестный", а затем мне нужно вернуться туда позже и изменить это для просмотра файла...

http://www.nihilogic.dk/labs/canvas2image/

4

Вы можете использовать localStorage. Это эквивалент файлов cookie Html5. Кажется, он работает на Chrome и Firefox, но на Firefox, мне нужно было загрузить его на сервер. То есть, тестирование непосредственно на моем домашнем компьютере не сработало.

Я работаю над примерами HTML5. Перейдите к http://faculty.purchase.edu/jeanine.meyer/html5/html5explain.html и прокрутите до лабиринта. Информация для восстановления лабиринта хранится с использованием localStorage.

Я пришел в эту статью, ища HTML5 JavaScript для загрузки и работы с XML файлами. Это то же самое, что и старый html и JavaScript????

3

Как уже упоминалось, File API, а также FileWriter и FileSystem API-интерфейсы могут использоваться для хранения файлов на клиентской машине из контекста вкладки/окна браузера.

Однако есть несколько вещей, относящихся к последним двум API, о которых вы должны знать:

  • Реализации API-интерфейсов в настоящее время существуют только в браузерах на основе хрома (Chrome и Opera)
  • Оба API были сняты со стандартного трека W3C 24 апреля 2014 года и на данный момент являются собственностью
  • Удаление (теперь запатентованных) API-интерфейсов от реализации браузеров в будущем - это возможность
  • песочница (расположение на диске, за пределами которого файлы не могут произвести никакого эффекта) используется для хранения файлов, созданных с помощью API
  • Используется виртуальная файловая система (структура каталогов, которая необязательно существует на диске в той же форме, что и при доступе из браузера) представляет файлы, созданные с помощью API

Вот простые примеры того, как API используются, прямо или косвенно, в тандеме, чтобы сделать это:

BakedGoods *

bakedGoods.get({
        data: ["testFile"],
        storageTypes: ["fileSystem"],
        options: {fileSystem:{storageType: Window.PERSISTENT}},
        complete: function(resultDataObj, byStorageTypeErrorObj){}
});

Использование необработанных файлов, API FileWriter и FileSystem

function onQuotaRequestSuccess(grantedQuota)
{

    function saveFile(directoryEntry)
    {

        function createFileWriter(fileEntry)
        {

            function write(fileWriter)
            {
                var dataBlob = new Blob(["Hello world!"], {type: "text/plain"});
                fileWriter.write(dataBlob);              
            }

            fileEntry.createWriter(write);
        }

        directoryEntry.getFile(
            "testFile", 
            {create: true, exclusive: true},
            createFileWriter
        );
    }

    requestFileSystem(Window.PERSISTENT, grantedQuota, saveFile);
}

var desiredQuota = 1024 * 1024 * 1024;
var quotaManagementObj = navigator.webkitPersistentStorage;
quotaManagementObj.requestQuota(desiredQuota, onQuotaRequestSuccess);

Хотя API-интерфейсы FileSystem и FileWriter больше не соответствуют стандартным трекам, их использование может быть оправдано в некоторых случаях, на мой взгляд, потому что:

  • Возобновленный интерес у недействующих поставщиков браузеров может вернуть их обратно.
  • Проникновение на рынок реализующих (на основе хромовых) браузеров является высоким.
  • Google (основной вклад в Chromium) не дал и не закончил API API

Однако, если "некоторые случаи" охватывают ваши собственные, вы должны решить.

* BakedGoods поддерживается не кем иным, как этим парнем прямо здесь:)

0

Вот учебник по экспорту файлов в формате ZIP:

Перед тем, как начать работу, есть библиотека для сохранения файлов, имя библиотеки - fileSaver.js. Здесь вы можете найти эту библиотеку. Давайте начнем. Теперь включите необходимые библиотеки:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.4/jszip.min.js"  type="text/javascript"></script>
<script type="text/javascript" src="https://fastcdn.org/FileSaver.js/1.1.20151003/FileSaver.js" ></script>

Скопируйте этот код, и этот код загрузит zip файл с файлом hello.txt, имеющим контент Hello World. Если все работает нормально, это загрузит файл.

<script type="text/javascript">
    var zip = new JSZip();
    zip.file("Hello.txt", "Hello World\n");
    zip.generateAsync({type:"blob"})
    .then(function(content) {
        // see FileSaver.js
        saveAs(content, "file.zip");
    });
</script>

Это загрузит файл с именем file.zip. Вы можете прочитать здесь: http://www.wapgee.com/story/248/guide-to-create-zip-files-using-javascript-by-using-jszip-library

Ещё вопросы

Сообщество Overcoder
Наверх
Меню