Pytanie Wygeneruj trochę xml w javascript, poproś użytkownika o zapisanie


Chciałbym zrobić dokument XML w JavaScript, a następnie pojawi się okno dialogowe zapisu.

  1. Jest OK, jeśli muszą kliknąć, zanim nastąpi zapis.
  2. To * nie * OK, jeśli * mam * używać IE, aby to osiągnąć (w ogóle nie potrzebuję go wspierać). Jednak Windows jest wymaganą platformą (więc Firefox lub Chrome są preferowanymi przeglądarkami, jeśli mogę to zrobić tylko w jednej przeglądarce).
  3. To * nie * OK, jeśli potrzebuję serwera WWW. Ale na odwrót, nie chcę wymagać, aby JavaScript był uruchamiany tylko w pliku lokalnym, tj. W podwyższonych uprawnieniach - jeśli to możliwe. To znaczy, chciałbym uruchomić lokalnie lub na * statycznym * hoście. Ale lokalnie jest OK.
  4. W porządku, aby to zrobić, trzeba się pochylić do tyłu. Plik nie będzie bardzo duży, ale dostęp do Internetu może tam być, być nierówny lub po prostu nie być w ogóle możliwy - patrz (3).

Do tej pory jedyne pomysły, jakie widziałem, to zapisanie pliku XML w elemencie iframe i zapisanie tego dokumentu - ale wydaje się, że można to zrobić tylko w IE? Ponadto mogę zbudować URI danych i umieścić go w łączu. Obawiam się, że po prostu otworzy plik XML w oknie, zamiast zachęcić użytkownika do jego zapisania.

Wiem, że jeśli wymagam, aby JavaScript był lokalny, mogę podnieść uprawnienia i po prostu zapisać plik (lub mam nadzieję, że pojawi się okno dialogowe zapisu). Wolałbym jednak rozwiązanie, w którym nie potrzebuję podniesionych uprawnień (nawet rozwiązanie tylko dla Firefoksa 3.6).

Przepraszam, jeśli to obraża czyjąś wrażliwość (na przykład, nie wspiera każdej przeglądarki). Zasadniczo chcę napisać aplikację offline, a JavaScript / HTML / CSS wydają się być najlepszym kandydatem, biorąc pod uwagę złożoność wymagań i dostępny czas. Mam jednak ten jeden wymóg, aby móc zapisać dane, które należy pokonać, zanim będę mógł wybrać tę linię rozwoju.


16
2018-02-09 01:37


pochodzenie


Uruchomiłem test z danymi uri, a jeśli ustawisz typ MIME w niewłaściwy sposób, możesz zmusić użytkownika do zapisania danych po kliknięciu łącza. Niezwykle brzydkim zastrzeżeniem jest to, że nie można podać nazwy pliku. I chyba, że ​​przeglądarka domyślnie pyta, gdzie i jaka nazwa podczas zapisywania pobrań, po prostu zapisuje jako ogromną brzydką nazwę w folderze pobierania, który musisz znaleźć, i zmień nazwę z rozszerzeniem xml, aby zobaczyć. To nie jest rozwiązanie. - Adam Luter
Jeśli nie chcesz mieć pliku JS jako lokalnego odniesienia, to gdzie jest on obsługiwany, jeśli serwer WWW nie jest opcją? - Jonathan
Dlaczego XML musi być utworzony ze strony internetowej? Zamiast tego możesz utworzyć małą, prostą (bez GUI) aplikację komputerową. - Bill Paetzke
@ Jonathan, idea jest elastyczna, teoretycznie mogłabym mieć całą aplikację jako pojedynczy plik html siedzący w dowolnym miejscu lub przynajmniej zwykłą statyczną kolekcję plików umieszczonych w dowolnym miejscu. Tak więc, nie chcę rezygnować z elastyczności posiadania go na przykład na statycznym serwerze sieciowym (tyle, że nie chcę, aby serwer WWW był wymagany). Ale biorąc pod uwagę wybór między tymi dwoma, muszę wybrać "jako plik lokalny", ponieważ nie mogę polegać na łączności sieciowej. - Adam Luter
@Bill Nie jestem zainteresowany rozwojem w niczym innym niż HTML / JS / CSS. Mogę z łatwością wybrać inne języki, platformy itp. Ale biorąc pod uwagę moje zasoby i tylko moje kaprysy, to jest mój wybór języka i platformy. - Adam Luter


Odpowiedzi:


Co powiesz na to pobierz scenariusz?

Oparte na Flash i jQuery, które mogą wyświetlić okno dialogowe do zapisania pliku na twoim komputerze.

Downloadify.create('downloadify',{
  filename: function(){
    return document.getElementById('filename').value;
  },
  data: function(){ 
    return document.getElementById('data').value;
  },
  onComplete: function(){ 
    alert('Your File Has Been Saved!'); 
  },
  onCancel: function(){ 
    alert('You have cancelled the saving of this file.');
  },
  onError: function(){ 
    alert('You must put something in the File Contents or there will be nothing to save!'); 
  },
  swf: 'media/downloadify.swf',
  downloadImage: 'images/download.png',
  width: 100,
  height: 30,
  transparent: true,
  append: false
});

6
2018-02-20 05:07



Flash to jedyny sposób, w jaki kiedykolwiek widziałem, aby robić to, o co prosisz. Ta odpowiedź (jQuery / event driven) jest bardzo eleganckim rozwiązaniem. - Jonathan Julian
Tak, to prawdopodobnie będzie jedyna odpowiedź na moje pytanie - nawet jeśli nie chcieć polegać na fleszu. (Nie powiedziałem jednak: P). Zawsze mogę polegać na lampie błyskowej lub podwyższone przywileje. S.Mark, czy wiesz, że istnieje odpowiednik ładowania pliku przez javascript? (Ponownie, oczywiście, monitując użytkownika). - Adam Luter
Jeśli komuś nie przeszkadza wyjaśnienie tego punktu - pracuję z programistów flash, ale nigdy sam z Flash - strona mówi, że jest skompilowana tylko do użytku online. Zakładam, że mogę go również skompilować do pracy na miejscu? - Adam Luter
@Adam - Tak, możesz skompilować do użytku lokalnego - ale nie "za". W oknie dialogowym "Ustawienia publikowania" Flash pyta, czy chcesz mieć tylko "dostęp do sieci", czy też "dostęp lokalny". Chyba że nie odnosimy się do tego samego. - Moshe
@Moshe, dzięki za smakołyk - nigdy nie pracowałem w flash przed. To by było ok ponieważ mogłem uzyskać dostęp do sieci, a następnie polegać na podwyższonych uprawnieniach dostępu lokalnego. Ale to oznacza, że ​​prawdopodobnie zacznę od podwyższonych uprawnień i będę robić flashowanie tylko wtedy, gdy skończę i chcę, aby działał na statycznym hoście internetowym. - Adam Luter


Korzystając z URI danych kodowanych base64, jest to możliwe tylko z html & js. Co możesz zrobić, to zakodować dane, które chcesz zapisać (w twoim przypadku, ciąg danych XML) w base64, używając biblioteki js jak jquery-base64 autorstwa carlo. Następnie umieść zakodowany ciąg w łączu i dodaj swój link do DOM.

Przykład użycia biblioteki, o której wspomniałem (oraz jquery):

<html>
<head>
    <title>Example</title>
</head>
<body>
    <script>
        //include jquery and jquery-base64 here (or whatever library you want to use)
        document.write('<a href="data:application/octet-stream;base64;charset=utf-8,' + $.base64.encode( "this is a example, which requires the jquery-base64 library to work... replace this text with your xml" ) + '">click to make save dialog</a>');
    </script>
</body>
</html>

... i pamiętaj, aby coś takiego wyglądać application/octet-stream więc przeglądarka nie próbuje go otworzyć.

Ostrzeżenie: niektóre starsze wersje IE nie obsługują base64, ale powiedziałeś, że to nie ma znaczenia, więc to powinno działać dobrze dla ciebie.


4
2018-03-31 23:31



To jest świetne. Czy jest jakiś sposób, aby zapisać go na pulpicie jako rzeczywisty plik? Na przykład, przepychanie XMLa przez to i pobieranie go na stronę użytkowników jako "text.xml"? Teraz możesz przekazać dowolny ciąg, który zapisuje jako "pobierz" z tekstem w środku. - streetlight
Używając tej odpowiedzi, można ją zapisać na pulpicie jako rzeczywisty plik, ale nie znalazłem sposobu na ustawienie nazwy pliku. To, czego faktycznie powinieneś używać, to Interfejs API systemu plików HTML5... to pozwoli ci ustawić konkretną nazwę pliku. - slang


Bez żadnego wglądu w twoje specyficzne wymagania, nie poleciłbym czystego rozwiązania JavaScript / HTML. Z punktu widzenia użytkownika najprawdopodobniej uzyskasz najlepsze wyniki przy pisaniu natywnej aplikacji. Jeśli jednak będzie szybciej używać JavaScript / HTML, polecam korzystanie z lokalnej aplikacji obsługującej lekki serwer WWW, aby wyświetlać treści. W ten sposób możesz w łatwy sposób obsługiwać zapisywanie plików po stronie serwera, jednocześnie skupiając większość wysiłku na aplikacji front-end.

Możesz kodować serwer WWW w - na przykład - Python lub Ruby używając bardzo niewielu linii kodu i bez bibliotek zewnętrznych. Na przykład zobacz:


"""
Serves files out of its current directory.
Doesn't handle POST requests.
"""
import SocketServer
import SimpleHTTPServer

PORT = 8080

def move():
    """ sample function to be called via a URL"""
    return 'hi'

class CustomHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def do_GET(self):
        #Sample values in self for URL: http://localhost:8080/jsxmlrpc-0.3/
        #self.path  '/jsxmlrpc-0.3/'
        #self.raw_requestline   'GET /jsxmlrpc-0.3/ HTTP/1.1rn'
        #self.client_address    ('127.0.0.1', 3727)
        if self.path=='/move':
            #This URL will trigger our sample function and send what it returns back to the browser
            self.send_response(200)
            self.send_header('Content-type','text/html')
            self.end_headers()
            self.wfile.write(move()) #call sample function here
            return
        else:
            #serve files, and directory listings by following self.path from
            #current working directory
            SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)

httpd = SocketServer.ThreadingTCPServer(('localhost', PORT),CustomHandler)

print "serving at port", PORT
httpd.serve_forever()

Wreszcie - w zależności od tego, kto będzie używał twojej aplikacji, będziesz miał również możliwość skompilowania programu w Pythonie do formatu Frozen Binary więc użytkownik końcowy nie musi mieć zainstalowanego Pythona na swoim komputerze.


2
2018-02-19 02:20



Dziękuję Justin za bardzo dokładną odpowiedź. Moim ideałem jest to, że plik może być lokalnym html (lub folderem lokalnym html itp.) lub na statycznym hoście (taniej), gdy jest sieć. Na podstawie posiadanych zasobów nie chcę tworzyć "prawdziwej" aplikacji. (Ale jeśli tak, prawdopodobnie wybrałbym Ruby lub Python). Mrożenie Pythona to duży plus, jeśli się zepsułem. Ale tak naprawdę chcę tylko trzymać się statycznej aplikacji "web" html / js / css (minus sieć). Aplikacja jest "podstawowym wprowadzeniem danych, a następnie procesem do jej komponowania". Interfejs użytkownika będzie dość prosty i po prostu muszę zapisać / załadować stan jako XML. - Adam Luter
Nie ma za co. Myślę, że jeśli zamierzasz skorzystać z rozwiązania html / js / css, nadal będziesz potrzebował back-endu - aczkolwiek minimalistycznego. - Justin Ethier


Javascript nie może zapisywać na komputerze lokalnym. Twoje pytanie jest podobne do ten.

Proponuję utworzyć prostą aplikację komputerową.


1
2018-02-19 02:22



Dziękuję Bill, wiem, że to standardowa odpowiedź. Chciałbym mieć racjonalne powody, dla których DOM tak myśli <a href="mydoc.txt">Click</a> jest wystarczająco bezpieczny, aby zachęcić użytkownika do zapisania pliku (a w wielu dzisiejszych przeglądarkach nawet nie pyta ...). Ale jeśli użyłem JS do utworzenia pliku txt, powiedz jakiś kod pseudo podobny do: <a onclick="window.promptSave('It was a dark and stormy night...', 'text/plain', 'mydoc.txt')">Click</a>, jest to z natury mniej bezpieczne? Teoretycznie powinno być mniej bezpiecznie, aby ponownie poprosić sieć o dane, ponieważ nie jest to bezpieczne połączenie (http na https). - Adam Luter


Czy serwer PHP localhosta jest ok? Sieć tradycyjnie nie może zapisać na dysku twardym z powodu problemów związanych z bezpieczeństwem. PHP może przesyłać pliki, chociaż wymaga serwera.

Wtyczki Print to PDF są dostępne dla wszystkich przeglądarek. Zainstaluj raz, drukuj do PDF na zawsze. Następnie możesz użyć javascript lub Flash, aby wywołać funkcję Print.

Ponadto, jeśli tworzysz środowisko, w którym dostęp do Internetu jest nierówny, spójrz za pomocą VB.NET lub innego języka pulpitu.

EDYTOWAĆ:

Możesz użyć funkcji drukowania przeglądarki.


0
2018-02-19 01:58



Mosze, dziękuję za odpowiedź. (przeczytaj moje inne komentarze na temat korzystania z serwera sieciowego, lokalnego lub innego, a także o używaniu czegoś innego niż html / js / css). ja mieć używać XML-a, to tylko wymóg (a nie naprawdę okropny, biorąc pod uwagę dane). Ale nie wspomniałem w moim pytaniu (ponieważ było to osobne pytanie), że muszę mieć możliwość późniejszego załadowania tego samego pliku XML (tak, drukowanie do pliku PDF byłoby wspaniałe, z tym wyjątkiem, że nie mógłbym załadować z tego). Używanie funkcji drukowania jest sprytne, ale nie sądzę, że działałoby to dla danych XML. - Adam Luter
@Adam - Nie widzę niczego złego w XML. Dlaczego nie wydrukować pracy dla danych XML? Możesz wysyłać XML jako zwykły tekst do przeglądarki. Ładowanie XML można wykonać za pomocą Flasha lub jQuery, ponieważ XML może być załadowany do przeglądarki jak każdy inny plik (text / html). - Moshe
Guh, nienawidzę pól komentarza AJAX, ponieważ zawsze kończę tracenie zawartości po skończeniu pudełka, a następnie o wypadku (np. Przypadkowe uderzenie w backspace po trafieniu w zakładkę). W każdym razie - mówiłem, że myślę, że trasa print + XML jest dla użytkownika co najmniej zbyt trudna. Może nawet gorsze niż powiedzenie "hej kliknij tutaj, a następnie wybierz save / as, a następnie kliknij" (jeśli poszedłem na trasę, na której mogłem przynieść XML jako własną stronę). Po prostu chcę, aby była to normalna procedura oszczędzania / ładowania dla zdrowia / rozsądku użytkownika. (Wygląda więc na to, że Flash może mi pomóc lub podniesione przywileje). - Adam Luter


Szukasz czegoś podobnego to?

Jeśli PHP jest w porządku, byłoby znacznie łatwiej.


0
2018-02-19 01:57



Dziękuję tr4656, nie znam już api XML dostępnych w JS. Próbuję uzyskać ten xml zapisany na dysku lokalnym przez okno dialogowe zapisywania użytkownika. Podobnie (i to jest osobne pytanie), chcę też poprosić użytkownika o załadowanie pliku (ale znowu bez udziału serwera WWW). Jeśli tego nie zrobię, postaram się przekonać (nawet historyczną) o tym, dlaczego jest mniej bezpieczny (a nie tylko w to wierzyć). - Adam Luter
@Adam - Zgadzam się z tobą, że ten cały argument dotyczący bezpieczeństwa jest nieco fałszywy lub przynajmniej niewyjaśniony. - Moshe


W IE można użyć document.execCommand, ale zauważam, że IE nie jest opcją.

Oto coś, co wygląda na to, że może ci pomóc, chociaż nie wyświetli odpowiedzi w oknie SaveAs, https://developer.mozilla.org/en/Code_snippets/File_I%2F%2FOL.


0
2018-02-20 04:55



Jonathan, twoje połączenie jest zepsute, ale domyślam się, że jest to kod podwyższonego przywileju, o którym wspomniałem w drugim akapicie. W każdym razie dzięki! :) - Adam Luter


Jednym prostym, ale dziwnym sposobem na zrobienie tego, który nie wymaga żadnego Flasha jest stworzenie <a/> z a URI danych za jego href. To nawet ma całkiem dobre wsparcie dla różnych przeglądarek, chociaż dla IE musi to być przynajmniej wersja 8, a identyfikator URI musi być <32k. Wygląda jak ktoś inny na SO ma więcej do powiedzenia na temat.


0
2018-02-20 19:58



Tak, ale jak zauważam w moim komentarzu do pytania, dane uri nie będą działały w przypadku, gdy potrzebna jest jakaś rozsądna nazwa pliku. - Adam Luter
Jako mała aktualizacja: przynajmniej w Chrome możemy ustawić "rozsądne" nazwy plików za pomocą właściwości pobierania w <a / wideo>, co sprawia, że ​​praca z URI jest trochę bardziej realna ... - Richard Ambler


Dlaczego nie skorzystać z hybrydowej pamięci flash dla klienta i niektórych serwerów po stronie serwera. Większość ludzi ma flash, więc możesz domyślnie po stronie klienta, aby zaoszczędzić zasoby na serwerze.


0
2018-06-03 10:38