LEKCJA 04 - EXPRESS (p) - files - fetch /updated 3.11/

LEKCJA 04 - EXPRESS (p) - files - fetch /updated 3.11/
ukryj menu
SPEC
aktualizacja: 2021-11-03 10:14:39

Uwaga: proszę zwracać uwagę w jaki sposób są przedstawione/sformatowane dane na skrinach z przeglądarki

1. kodowanie formularza i upload plików

defaultowo przy wysłaniu danych w url formularz kodowany (właściwość enctype) jest: application/x-wwwform-urlencoded
natomiast przy upload-zie plików należy podać, jak poniżej - multipart/form-data


2. klient - konstrukcja formularza

<form enctype="multipart/form-data" method="POST" action="/handleUpload">kopiuj

w formularzu przykładowe inputy:

date // data zdjęcia
text // nazwa zdjęcia
file // zdjęcie


<input type="file" required accept="image/*" name="imagetoupload">  kopiuj

3. server - upload z użyciem modułu formidable

najpierw zainstaluj formidable w wersji 1.2.2

npm install formidable@1.2.2kopiuj

potem na serwerze

var formidable = require('formidable');kopiuj

obsługa danych formularza przychodzących postem (inputy i pliki):



app.post('/handleUpload', function (req, res) {

    let form = formidable({});

    form.uploadDir = __dirname + '/static/upload/'       // folder do zapisu zdjęcia

    form.parse(req, function (err, fields, files) {
 
        console.log("----- przesłane pola z formularza ------");

        console.log(fields);

        console.log("----- przesłane formularzem pliki ------");

        console.log(files);

        res.send("plik przesłany!")
    });
});kopiuj


Zadanie 1: zwróć dane dokładnie w takiej formie jak na skrinie, testuj w chrome


4. rozszerzenia

domyślnie pliki zapisywane są bez rozszerzenia, aby to zmienić:

form.keepExtensions = true   // zapis z rozszerzeniem plikukopiuj

Zadanie 2: zwróć dane dokładnie w takiej formie jak na skrinie, testuj w chrome

5. upload wielu plików

zmiana na kliencie

<input type="file" multiple required accept="image/*" name="imageupload">kopiuj

zmiana na serwerze

form.multiples = truekopiuj

Zadanie 3 i 4: zwróć dane dokładnie w takiej formie jak na skrinie, testuj w chrome



6. fetch


Fetch, technologia komunikacji klient serwer, zastępująca Ajaxa
Fetch jest przygotowany do przesyłania danych w postaci JSON-a, można jednak za jego pomocą przesyłać też pliki.
W większości kolejnych zadań pojawia się też temat asynchronicznego wywoływania funkcji - async/await




7. Wysłanie danych post-em na serwer - fetch

klient

funkcja wywoływana kliknięciem butona


function fetchPost() {
   
    const body = JSON.stringify({ a: 1, b: 2, c: "fetch" }) // body czyli przesyłane na serwer dane
   
    const headers = { "Content-Type": "application/json" } // nagłowek czyli typ danych
   
    fetch("/api", { method: "post", body, headers }) // fetch
        .then(response => response.json())
        .then(
            data => console.log(data) // dane odpowiedzi z serwera
        )

}kopiuj



wywołanie w onclick

document.getElementById("bt").onclick = function () {
    fetchPost()
}kopiuj


serwer - odebranie i odesłanie danych

dane wysłane postem odbierzemy na serwerze Express z użyciem parsera jak na poprzednich zajeciach




console.log(req.body); 
kopiuj
res.setHeader('content-type', 'application/json'); // nagłówek
res.end(JSON.stringify(req.body)); // odsyłamy dane do klienta w postaci stringakopiuj




dane można wysłać też asynchronicznie, z użyciem pary async/await:

klient


w poniższym kodzie funkcja musi być async, wewnątrz funkcji fetch musi być await

async function fetchPostAsync() {
   
    const body = JSON.stringify({ a: 3, b: 4, c: "fetch async" }) // body - dane
 
    const headers = { "Content-Type": "application/json" } // nagłówek
   
    let response = await fetch("/api", { method: "post", body, headers }) // fetch

    if (!response.ok)
        return response.status
    else
        return await response.json()


}kopiuj


Zadaniem funkcji jest zwrocić odpowiedź z serwera, dlatego jest inaczej wywołana w kliku niż poprzednia
Aby uniknąć kolejnych then(), jak w poprzednim przykładzie, wywołanie funkcji też musi być await

document.getElementById("bt").onclick = async function () {
    let json = await fetchPostAsync()
    console.log(json)
}kopiuj


powyższy kod sprzyja też rozdzieleniu funkcji od jej wykonania, np manipulacja interfejsem strony odbywa się teraz niezależnie od fetch-a

Zadanie 5: wykonaj jedno z zadań 5,6,7 z poprzedniej lekcji, używając fetcha zamiast Ajaxa

8. pobranie danych json z serwera

mamy dane w pliku json na serwerze

[
    {
        "id": 1,
        "car_name": "Honda",
        "car_type": "CRV",
        "car_year": 2003,
        "hex_color": "#237701",
        "damaged": true
    },
    {
        "id": 2,
        "car_name": "Honda",
        "car_type": "Prelude",
        "car_year": 1986,
        "hex_color": "#f7f23d",
        "damaged": false
    },
    {
        "id": 3,
        "car_name": "Mercedes-Benz",
        "car_type": "Sprinter 2500",
        "car_year": 2012,
        "hex_color": "#721ac8",
        "damaged": false
    },
    {
        "id": 4,
        "car_name": "Acura",
        "car_type": "RSX",
        "car_year": 2004,
        "hex_color": "#dcbeb7",
        "damaged": true
    },
    {
        "id": 5,
        "car_name": "Land Rover",
        "car_type": "Range Rover Sport",
        "car_year": 2010,
        "hex_color": "#3e29b2",
        "damaged": false
    }
]kopiuj



klient

const headers = { "Content-Type": "application/json" }

fetch("/api", { method: "get", headers })
    .then(response => response.json())
    .then(
        data => console.log(data)
    )kopiuj


serwer

require danych json

var json = require("./data.json")kopiuj

w GET /api odsyłamy nasze dane json


res.setHeader('content-type', 'application/json'); // nagłówek
res.end(JSON.stringify(json));kopiuj


Uwaga: taką sama funkcjonalność jak powyżej zapewnia wbudowana w expressa funkcja res.json()

res.json({a:1})kopiuj

9. fetch data - simple api

dane json z poprzedniego zadania mają być czytane przy takich adresach w pasku przegladarki

/
/all
/first
/hondakopiuj


dodaj na serwerze odpowiednie endpointy (get-y) 

tym razem nie ma strony html tylko serwer i zwracane dane json w odppowiednich get-ach

10. redirect to car api

do poprzedniego ćwiczenia dodaj stronę cars.html, a na niej prosty routing



kierujący do odpowiednich get-ów na serwerze

11. post file to server by fetch

api fetch-a służy też do wysyłania plików, z użyciem obiektu klasy FormData
zastępującej funkcjonalnie formularz

klient

var fd = new FormData()

fd.append("file", document.getElementById("fileInput").files[0]) // plik z inputa

const body = fd

const headers = { "Content-Type": "application/json" }

fetch("/api", { method: "post", body })
    .then(response => response.json())
    .then(data => console.log(data) // odesłane z serwera dane
    .catch(error => console.log(error)) // ew błądkopiuj


serwer


moduł formidable działa jak w ćwiczeniach 1-4

zadanie - po uploadzie odeślij takie dane do klienta w formacie json i pokaż na tej samej stronie:


{
    "title": "file uploaded!",
    "fileName": "plik.png",
    "date": "2021-02-11T09:46:58.391Z"
}kopiuj



12. get image by fetch - zadanie dodatkowe

html

na początek ładuje się domyślny obrazek

<img src="default.gif" alt="image" id="img">kopiuj

js

dane pliku wracają w postaci tzw blob-a
przeczytamy go obiektem klasy FileReader()
który zwraca dane pliku w postaci stringa base64
warto wylogować i podejrzeć

fetch("/url",
    { mode: 'cors' })
    .then(response => response.blob())
    .then(blob => {
        console.log(blob);

        const reader = new FileReader();

        reader.addEventListener("load", function () {
            console.log(reader.result) // to jest plik obrazka w postaci stringa  base64           
            document.getElementById("img").src = reader.result; // wyświetlenie image
        }, false);

        reader.readAsDataURL(blob); // tutaj reader zaczyna czytać plik, powyższy event load to koniec tego czytania

        //
    });
kopiuj



serwer

zadanie - dodaj get-y na serwerze, który obsłuży trzy butony jak na obrazku


13. random - post data to server by fetch, download image by fetch - zadanie dodatkowe

przebieg ćwiczenia: 

a) button "random" wywołuje na serwerze funkcję losującą cyfrę z przedziału 1-3

b) wylosowana cyfra po powrocie z serwera jest widoczna w konsoli przeglądarki

c) button "compare" wysyła na serwer cyfrę wybraną z selecta i wywołuje na serwerze funkcję porównującą wysłaną cyfrę i wylosowaną

d) wynik porównania wraca do klienta i jest widoczny w konsoli

e) jeśli wynik porównania jest == true, pobierany jest fetchem obrazek A, jeśli nie to B