JavaScript: ako sledovať websocket upload?

hknmtt

  • ***
  • 162
    • Zobrazit profil
    • E-mail
JavaScript: ako sledovať websocket upload?
« kdy: 11. 12. 2024, 08:37:54 »
Nahravam subor cez websocket. Subor je obycajny file objekt z file inputu a odosiela sa ako ws.send(file). Chcem vsak sledovat priebeh nahravania. Ako by to bolo mozne? Je mi jedno ci sledujem citanie dat zo suboru alebo odosielanie dat od websocketu, proste len chcem mat prehlad. Urcite sa vsak chcem vyhnut implementacii "manualneho" upload cez WebSocketStream. A rozkuzkovat subor cez file.slice(offset, limit) a posielat to takto cez ws.send(chunk) nefunguje, takze tadial cesta nevedie.


Jen Kings

  • ***
  • 131
  • Hryprodva.cz
    • Zobrazit profil
    • Hry Pro Dva
    • E-mail
Re:JavaScript: ako sledovať websocket upload?
« Odpověď #1 kdy: 11. 12. 2024, 09:17:26 »
S zkoušel jsi soubor číst jako stream, a ten rourovat do websocketu? Nad streamem si uložíš reader, který ti poskytne callbackované informace o tom kolik toho přenesl, takže si jen na začátku vyčteš ze souboru jeho původní velikost, a pak si do další globálky v callbacku přičítáš kolik již bylo přeneseno, takže pak spočítáš procentuální progress
Sice to na pozadí funguje dost podobně jako to slicování, ale ne úplně. Nevím jakým způsobem to zmíněné "slicování a posílání nefunguje", takže nedovedu říct, jestli tohle je pro tebe cesta, nebo ne.

hknmtt

  • ***
  • 162
    • Zobrazit profil
    • E-mail
Re:JavaScript: ako sledovať websocket upload?
« Odpověď #2 kdy: 11. 12. 2024, 09:34:53 »
Nevím jakým způsobem to zmíněné "slicování a posílání nefunguje", takže nedovedu říct, jestli tohle je pro tebe cesta, nebo ne.

Kód: [Vybrat]
        const MB = 1024*1024
        let offset = 0
        while (offset < file.size) {
          const payload = file.slice(offset, offset+MB)
          offset += MB
          up.send(payload)
          progressor(payload.size)
        }

toto mi produkuje prazdne wbesocket spravy. Cize ws.send() sa vola, lenze nic neodosiela. Predpokladam ze kvoli tomu ze ws.bufferedAmount sa s kazdym volanim ws.send() zvysuje a ked vykonava samotny send tak mozno zisti ze ma neplatne udaje lebo sa velkost znovu zvysila tak neodosle nic? Moc mi to logiku nedava, ale je to JS a tam logika neexistuje.

Taktiez by to mohlo mat nieco s tym ze payload prestane mat platnu adresu kvoli slucke a oneskorenemu pristupu do pamete, takze ked websocket realne odosiela data tak blob/buffer na ktory payload odkazoval v ws.send uz je neplatny? Nemam sajnu.

Jen Kings

  • ***
  • 131
  • Hryprodva.cz
    • Zobrazit profil
    • Hry Pro Dva
    • E-mail
Re:JavaScript: ako sledovať websocket upload?
« Odpověď #3 kdy: 11. 12. 2024, 09:51:28 »
a ten stream jsi zkoušel ? Dělá to to stejné ?


Kód: [Vybrat]
const stream = file.stream();
const reader = stream.getReader();

Kód: [Vybrat]
    function readAndSend() {
        reader.read().then(({ done, value }) => {
            if (done) {
                return; /* odesláno */
            }
            ws.send(value);

            //value.length  -> obsahuje objem který se teď odeslal
            readAndSend();
        }).catch((error) => {
            //ERROR
        });
    }

    readAndSend();


To je teď jen tak z hlavy, ber to spíš jako pseudokód a náznak toho, jak bych si představoval že by to mohlo fungovat

hknmtt

  • ***
  • 162
    • Zobrazit profil
    • E-mail
Re:JavaScript: ako sledovať websocket upload?
« Odpověď #4 kdy: 11. 12. 2024, 11:37:14 »
Toto riesenie sa zda ze funguje. Akurat mam problem s tym, ze ked posielam subor v celku, bez tohto riesenia, tak v logu mam jednu prazdnu odoslanu spravu. Ked to rozkuskujem cez ten reader, tak odosielam plno sprav s datami. Co je spravne. Ale nastava tu problem, ze websocket berie kazdu spravu ako samostatnu, takze na backende je to akoby som posielal N suborov a nie sucasti jedneho suboru, kvoli tomu ako funguje frejmovane v websocket protokole. Takze musim upravit kvoli tomu backend. Co sa mi moc nepaci, ale je to ok lebo aj tak je len jedno ws spojenie na subor. Ale keby slo nejak ws povedat ze teraz idem odosielat jednu spravu ktora ma N bajtov ale pojde to rozsekane, tak by to bolo lepsie. Ratam ale ze by som najskor musel pouzit WebSocketStream aby som nemusel ladit backend a riesit to len na frontende.


Jen Kings

  • ***
  • 131
  • Hryprodva.cz
    • Zobrazit profil
    • Hry Pro Dva
    • E-mail
Re:JavaScript: ako sledovať websocket upload?
« Odpověď #5 kdy: 11. 12. 2024, 11:59:37 »
JJ, asi bys to musel celé "znásilnit" víc do hloubky, a to ještě s poměrně nejistým výsledkem. Moudřejší a méně nákladné asi bude na konci poslat nějaký definovaný packet s CRC,nebo lépe hashem, toho souboru, a backend si k tomu přiohnout.

hknmtt

  • ***
  • 162
    • Zobrazit profil
    • E-mail
Re:JavaScript: ako sledovať websocket upload?
« Odpověď #6 kdy: 11. 12. 2024, 12:21:16 »
Nie je mozne nejak ten file/blob zabalit, pretazit nejake read metody kde si ja zaznamenam dlzku bajtov a len poslat data dalej?

fos4

Re:JavaScript: ako sledovať websocket upload?
« Odpověď #7 kdy: 13. 12. 2024, 13:40:43 »
A co posílat informace ze serveru na klienta, kolik dat se už poslalo? Na serverové se ví, kolik dat přiteklo, takže pomocí něakého identifikátoru, který si client/server vymění, posílat informace skrze WS kolik toho bylo přijato.

Nebo potom použit XMLHttpRequest, který to umí :-/

hknmtt

  • ***
  • 162
    • Zobrazit profil
    • E-mail
Re:JavaScript: ako sledovať websocket upload?
« Odpověď #8 kdy: 13. 12. 2024, 14:06:16 »
Hej aj to bola moznost ale je to zbycona datova prevadzka. Navyse dost nelogicka kedze ja mam cely subor k dispozicii a pytat sa protistrany kolko som im poslal dat je proste javascriptovina.

Ak by niekto potreboval tak toto pouzivam:
Kód: [Vybrat]
        const reader = file.stream().getReader()
        const handler = function({ done, value }) {
          if (!done) {
            up.send(value)
            progressor(value.length) <-- posielam von kde aktualizujem celkovy upload a pocitam percenta
            reader.read().then(handler)
          }
        }
        reader.read().then(handler)