Jak nahrávat soubory na server pomocí Fetch API

Nahrávání souborů je v dnešní době jednou z nejběžnějších funkcí webové aplikace. Existuje mnoho knihoven JavaScriptu, které zvládnou nahrávání souborů jako vánek.

Ale nenačteme celou knihovnu jen pro tuto jedinou funkci, kterou lze snadno zvládnout v nativním JavaScriptu pomocí Fetch API. Fetch je slibná moderní náhrada XHR pro vytváření požadavků HTTP v prohlížeči.

Načíst nahrání souboru

Pojďme na váš web přidat následující vstupní prvek HTML:

<input type="file" id="avatar">

Nyní přidejte posluchač událostí na vstup, který se spustí, když uživatel vybere soubor:

// select file input
const input = document.getElementById('avatar');

// add event listener
input.addEventListener('change', () => {
    uploadFile(input.files[0]);
});

Dále přidejte uploadFile() metoda, která obdrží File objekt jako vstup a nahraje jej na server s fetch() pomocí rozhraní FormData:

const uploadFile = (file) => {

    // add file to FormData object
    const fd = new FormData();
    fd.append('avatar', file);

    // send `POST` request
    fetch('/upload-avatar', {
        method: 'POST',
        body: fd
    })
    .then(res => res.json())
    .then(json => console.log(json))
    .catch(err => console.error(err));
}

Ověřte typ a velikost souboru

Před zahájením nahrávání na server můžete také ověřit vlastnosti (jako je typ souboru a velikost souboru) souboru:

const uploadFile = (file) => {

    // check file type
    if(!['image/jpeg', 'image/gif', 'image/png', 'image/svg+xml'].includes(file.type)) {
        console.log('Only images are allowed.');
        return;
    }

    // check file size (< 2MB)
    if(file.size > 2 * 1024 * 1024) {
        console.log('File must be less than 2MB.');
        return;
    }

    // ...
}

Ovládání nahrávání souborů na straně serveru pomocí Node.js

Zde je příklad kódu, který zpracovává výše uvedený požadavek na nahrání souboru v Node.js. Používám express-fileupload — jednoduchý Express middleware pro nahrávání souborů. Analyzuje multipart/form-data requests , rozbalí soubory, pokud jsou k dispozici, a zpřístupní je pod req.files vlastnost:

app.post('/upload-avatar', async (req, res) => {
    try {
        if(!req.files) {
            res.send({
                status: false,
                message: 'No file uploaded'
            });
        } else {
            //Use the name of the input field (i.e. "avatar") to retrieve the uploaded file
            let avatar = req.files.avatar;
            
            //Use the mv() method to place the file in upload directory (i.e. "uploads")
            avatar.mv('./uploads/' + avatar.name);

            //send response
            res.send({
                status: true,
                message: 'File is uploaded',
                data: {
                    name: avatar.name,
                    mimetype: avatar.mimetype,
                    size: avatar.size
                }
            });
        }
    } catch (err) {
        res.status(500).send(err);
    }
});

Ovládání nahrávání souborů na straně serveru pomocí Spring Boot

Pokud plánujete použít Spring Boot pro back-end, zde je ukázkový úryvek kódu, který zpracuje výše uvedený požadavek na nahrání souboru ve Spring Boot:

@PostMapping("/upload-avatar")
@ResponseBody
public ResponseEntity<String> fileUpload(MultipartFile avatar) {
    try {

        // upload directory - change it to your own
        String UPLOAD_DIR = "/opt/uploads";

        // create a path from file name
        Path path = Paths.get(UPLOAD_DIR, avatar.getOriginalFilename());

        // save the file to `UPLOAD_DIR`
        // make sure you have permission to write
        Files.write(path, avatar.getBytes());
    }
    catch (Exception ex) {
        ex.printStackTrace();
        return new ResponseEntity<>("Invalid file format!!", HttpStatus.BAD_REQUEST);
    }

    return new ResponseEntity<>("File uploaded!!", HttpStatus.OK);
}