Запуск загрузки файла без запроса сервера
Привет,
Я работаю над JS-приложением, которое выполняет некоторую сложную работу и записывает некоторую информацию (фактически, до сотен строк) на <div>
.
Моя цель - создать кнопку "Сохранить журнал", которая запускает диалог загрузки браузера, чтобы сохранить содержимое моего журнала <div>
.
Более кратко, это требования к этой функции:
- Конечный пользователь должен иметь полный контроль над файлом. Он/она должен иметь возможность сохранять/архивировать его для дальнейшего использования, отправлять его в отдел поддержки, чтобы получить помощь в решении какой-либо проблемы, загрузить ее обратно в приложение и т.д. Таким образом, API-интерфейс HTML5 Web Storage здесь не помогает (данные получить сохраненный в определенном браузером месте и не будет легко извлекаться, за исключением JS, который его создает).
- Приложение должно работать в автономном режиме (по крайней мере, при некоторых обстоятельствах). Это и эффективность, вот почему я отбросил идею POSTing данных на сервер, чтобы вернуть его с заголовком "Content-disposition".
- Файл должен быть помечен как
text/plain
, поэтому браузер может предлагать действия по умолчанию (например, "Открыть в блокноте" ), как при обычной загрузке файла. Это можно рассматривать как особый аспект первого требования.
- Говорить пользователю о том, чтобы скопировать содержимое
<div>
в текстовый редактор и сохранить его там, безусловно, ужасно, и именно поэтому я пытаюсь избежать.
Я искал этот сайт, на сайтах WHATWG и W3C и в Интернете в целом без успеха. Это вообще возможно?
Самое близкое, что у меня есть, - это использовать data:
url. Моя первая попытка, выполняющая POST-действие, не смогла получить тип контента, поэтому он вернется к эвристике UA. Мне было немного лучше, стиля ссылку <a>
, чтобы выглядеть как кнопка и придать ей атрибут type
, но тогда UA будет играть слишком умно и отображать контент вместо сохранения (и попросить пользователя сохранить файл из браузера на этом этапе становится еще хуже, чем при использовании подхода "копировать-вставить", поскольку сохранение страниц сильно варьируется между браузерами).
Если бы был какой-то способ объединить URL-адрес data:
с подсказкой "content-disposition", все могло бы стать очень плавным.
С уважением,
Herenvardo
Ответы
Ответ 1
К сожалению, это не то, что вы можете сделать с обычными возможностями браузера. Что-то вроде flash или зависящего от браузера плагина доставит вам то, что вам нужно, но ограничения безопасности в javascript не позволят вам загружать произвольные данные, созданные в браузере.
Также URL-адрес 'data' не поддерживается во всех комбинациях браузера/версии. Я не уверен, ограничены ли ваши пользователи тем браузером, который они используют или нет, но могут ограничить то, что вы можете сделать с этим решением.
Ответ 2
Это решение немного запутанно, но будет работать для ваших нужд, возможно, это вариант.
Создайте собственный веб-сервер, который просто возвращает содержимое любого GET или POST как текстовое /plain.
Принимать этот веб-сервер в том же поле, что и веб-приложение, но работать на другом порту. Когда вы нажимаете кнопку "Сохранить журнал", запрос отправляется на пользовательский сервер и возвращается текстовый файл.
Здесь доказательство сервера концепции в Java, которое будет делать именно это:
// After running this program, access with your browser at 127.0.0.1:8080
import java.net.*;
import java.io.*;
public class ReturnTextFile
{
public static void main(String[] args)
{
try
{
ServerSocket server = new ServerSocket(8080);
Socket connection = null;
while (true)
{
try
{
connection = server.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String input = in.readLine();
// TODO: Clean up input
Writer out = new OutputStreamWriter(connection.getOutputStream());
String output = "HTTP/1.1 200 OK\n" +
"Connection: close\n" +
"Content-Disposition: attachment; filename=log.txt\n" +
"Content-Type: text/plain; charset=utf-8\n" +
"\n";
output += input;
out.write(output);
out.flush();
connection.close();
}
catch (IOException ex)
{
ex.printStackTrace();
}
finally
{
if (connection != null)
{
connection.close();
}
}
}
}
catch (IOException ex)
{
ex.printStackTrace();
}
}
}
Ответ 3
Вы можете установить тип контента в URL data:
, что-то вроде этого:
data:text/plain,this is some text
Тем не менее, проблема в том, что браузер автоматически отображает его как текст. У вас действительно есть два варианта, которые я вижу. Один из них заключается в том, что вы задаете тип двоичного типа, чтобы браузер не пытался его отобразить, или что у вас есть тип text/plain, и попросите пользователя щелкнуть правой кнопкой мыши и сохранить его. Возможно, что-то здесь может помочь?
Ответ 4
Я был на этом пути, и я также хотел сделать это исключительно на стороне клиента. Но это невозможно. Единственный способ запустить диалог сохранения без каких-либо проблем - это сделать запрос HTTP POST и ответить сервером заголовком content-disposition
.
У меня есть желаемая функциональность в фрагментах кода на мой пыльный старый блог. У меня есть форма с одним скрытым полем, указывающим на пользовательский обработчик HTTP. Javascript захватывает внутренний текст блока кода, помещает его в скрытое поле и отправляет форму. Сервер отвечает всем телом запроса вместе с требуемыми заголовками. Нет обновления, вы щелкаете по нему, и вы получаете диалог сохранения. Отлично работает!