JavaScript >> Javascript tutorial >  >> Tags >> PHP

Sådan uploades filer til en server med almindelig JavaScript og PHP

At skrive koden til at uploade billeder til en server fra bunden virker som en meget skræmmende opgave. Jeg vil lave en meget simpel uploadformular for at demonstrere, hvordan fildata fungerer og kan overføres.

I dette selvstudie skal vi bygge en uploadformular med HTML , send filerne med JavaScript , og behandle og uploade dem med PHP .

Bemærk, at dette ikke er beregnet til at være fuldt funktionel, sikker, valideret produktionskode. Det er simpelthen meningen at demonstrere på en enkel og ligetil måde, hvordan du laver din første uploadformular.

  • Se kilde på GitHub

Forudsætninger

  • En grundlæggende viden om HTML
  • En grundlæggende viden om PHP-syntaks og kodestruktur
  • En forståelse af lokale PHP-miljøer. Hvis du ikke ved, hvad det betyder, så læs venligst denne vejledning om, hvordan du opsætter et MAMP-miljø.

Mål

  • Byg den enklest mulige formular med HTML for at hente filer fra din lokale computer.
  • Send dataene fra en HTML-formular til et PHP-script med vanilla JavaScript.
  • Behandle dataene i PHP-scriptet og flyt de lokale filer til en uploads/ bibliotek på en server.

Opsætning

Som nævnt i forudsætningerne skal du have et grundlæggende kendskab til PHP og lokale servermiljøer.

Hvis du bruger en Mac, kan du oprette en server med en enkelt kommando. For at teste dette skal du oprette en fil kaldet test.php i den mappe efter eget valg. Jeg vil oprette en mappe kaldet local . Den fulde sti vil være Users/tania/local .

test.php
<?php echo 'This is only a test.';

I Terminal-applikationen, som jeg åbner ved at trykke på SPACEBAR + COMMAND og skriv Terminal, naviger til den mappe, du oprettede din fil i.

cd server
php -S localhost:8888

Du skulle nu være i stand til at gå til http://localhost:8888/test.php og se outputtet af koden.

Hvis du er på Windows, eller du ikke ønsker at bruge kommandolinjen, skal du konfigurere MAMP.

Opbygning af en uploadformular i HTML

I roden af ​​din lokale server skal du oprette en index.html fil. Vi laver bare et hurtigt skelet.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />

    <title>Upload Files</title>
  </head>

  <body>
    <!-- form goes here-->
  </body>
</html>

Lad os tilføje en HTML-webformular til body .

<form method="post" enctype="multipart/form-data">
  <input type="file" name="files[]" multiple />
  <input type="submit" value="Upload File" name="submit" />
</form>

I denne formular bruger vi POST HTTP-metoden, som viser, hvordan vi sender data. multipart/form-data værdi er påkrævet for at uploade filer i formularer.

Herfra opretter vi en filinputtype, der tager en række filer (files[] ), og vi angiver multiple for at tillade, at mere end én fil kan vælges. files[] kan have et hvilket som helst navn - du kan bruge uploads[] eller images[] , men jeg kaldte det files[] for nemheds skyld.

Endelig har vi en send-knap. Da næste trin vil være at tilføje et script, lad os bare tilføje et link til den JavaScript-fil, vi vil oprette.

<script src="upload.js"></script>

Og det er alt, hvad vi behøver for udsigten.

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />

    <title>Upload Files</title>
  </head>

  <body>
    <form method="post" enctype="multipart/form-data">
      <input type="file" name="files[]" multiple />
      <input type="submit" value="Upload File" name="submit" />
    </form>

    <script src="upload.js"></script>
  </body>
</html>

Afsendelse af formulardata via JavaScript

Lige nu går det ingen vegne at klikke på send på formularen. Da vi ikke har en action der fører til en URL, vil formularen som standard blot sende til sig selv. Siden index.html er en html-fil, ikke en PHP-fil, kan ingen formularbehandling ske på denne side. I stedet sender vi formularen til PHP via JavaScript.

Opret en fil kaldet upload.js .

Lad os først definere to variable - URL'en, hvor vi vil sende dataene, og DOM-elementet for formularen.

upload.js
// Define processing URL and form element
const url = 'process.php'
const form = document.querySelector('form')

Vi tilføjer en begivenhedslytter for at holde øje med formularen, der sendes, men vi forhindrer, at standardhandlingen udløses.

// Listen for form submit
form.addEventListener('submit', (e) => {
  e.preventDefault()

  // ...
})

Lad os samle filerne med .files egenskab, og start en ny FormData() grænseflade.

// Gather files and begin FormData
    const files = document.querySelector('[type=file]').files;
    const formData = new FormData();
});

// ...

For hver fil, der er blevet indsendt, skal du tilføje den til files[] array.

// Append files to files array
for (let i = 0; i < files.length; i++) {
  let file = files[i]

  formData.append('files[]', file)
}

// ...

Brug endelig den indbyggede Fetch API til at POST dataene til den URL, vi har angivet. Udskriv svaret til konsollen (til testformål).

fetch(url, {
  method: 'POST',
  body: formData,
}).then((response) => {
  console.log(response)
})

Her er den færdige upload.js .

upload.js
const url = 'process.php'
const form = document.querySelector('form')

form.addEventListener('submit', (e) => {
  e.preventDefault()

  const files = document.querySelector('[type=file]').files
  const formData = new FormData()

  for (let i = 0; i < files.length; i++) {
    let file = files[i]

    formData.append('files[]', file)
  }

  fetch(url, {
    method: 'POST',
    body: formData,
  }).then((response) => {
    console.log(response)
  })
})

Nu - hvordan kan vi teste, om alle disse data går korrekt igennem? Lad os udskrive fildataene.

Opret en ny fil kaldet process.php , og udskriv indholdet af det superglobale array $_FILES , som vil indeholde dataene for alle vores filer.

process.php
<?php print_r($_FILES);

Når du har denne fil, kan du prøve at uploade et par filer via formularen. Jeg lavede en phplogo.png og testfile1.txt at teste med, og uploadede filen.

I Udviklerværktøjer under Konsolen , bør du se et svar som dette:

Udviklerværktøjer -> Konsol

Response {
  type: "basic",
  url: "http://localhost:8888/process.php",
  redirected: false,
  status: 200,
  ok: true, …
}

Hvis du ser status: 200 , betyder det, at filen ramte den korrekte URL, og URL'en eksisterer.

Klik nu på Netværk i Udviklerværktøjer fanen. Du bør se filnavnet process.php . Klik på filen, og klik på Svar . Der skulle du se outputtet af print_r($FILES) . Det vil se nogenlunde sådan her ud:

Udviklerværktøjer -> Netværk -> Svar

[files] => Array
(
  [name] => Array
  (
    [0] => phplogo.png
    [1] => testfile1.txt
  )

  [type] => Array
  (
    [0] => image/png
    [1] => text/plain
  )

  [tmp_name] => Array
  (
    [0] => /private/var/xxx
    [1] => /private/var/yyy
  )

  [error] => Array
  (
    [0] => 0
    [1] => 0
  )

  [size] => Array
  (
    [0] => 16610
    [1] => 12
  )
)

Nu ved vi, at de korrekte filer, sammen med alle deres tilknyttede data, er gået igennem. Succes!

Behandling af formulardata med PHP

Nu hvor vi samler alle filerne fra formularen og sender dem til process.php med JavaScript skal vi flytte fildataene med PHP.

Først vil vi gerne sikre os, at koden kun kører, når en POST-anmodning rammer filen.

process.php
<?php

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  // ...
}

Vi vil også gerne sikre os, at filer er gået igennem.

if (isset($_FILES['files'])) {
  // ...
}

Opret en mappe i roden af ​​dit projekt kaldet uploads . Denne mappe skal have 755 tilladelser til at acceptere indgående filer.

På dette tidspunkt opretter vi et array for fejl, angiver stien til den mappe, hvor uploads skal gå, og indstiller de godkendte udvidelser.

$errors = [];
$path = 'uploads/';
$extensions = ['jpg', 'jpeg', 'png', 'gif'];

Da brugeren kan uploade flere filer, opretter vi en $all_files variabel, få antallet af filer, der uploades, og lav en for løkke.

$all_files = count($_FILES['files']['tmp_name']);

for ($i = 0; $i < $all_files; $i++) {
    // ...
}

For hver fil får vi nu filnavnet, midlertidige fildata, type, størrelse og udvidelse.

$file_name = $_FILES['files']['name'][$i];
$file_tmp = $_FILES['files']['tmp_name'][$i];
$file_type = $_FILES['files']['type'][$i];
$file_size = $_FILES['files']['size'][$i];
$file_ext = strtolower(end(explode('.', $_FILES['files']['name'][$i])));

$file = $path . $file_name;

Nu kan vi sætte et par regler for filerne. Hvis filtypen ikke er på den godkendte liste over udvidelser, eller filen er for stor, føjer vi den til fejlarrayet. Jeg indstillede en filstørrelse på 2 megabyte.

if (!in_array($file_ext, $extensions)) {
    $errors[] = 'Extension not allowed: ' . $file_name . ' ' . $file_type;
}

if ($file_size > 2097152) {
    $errors[] = 'File size exceeds limit: ' . $file_name . ' ' . $file_type;
}

Hvis der ikke var nogen fejl, kan vi gå videre og flytte filen til uploads mappe med move_uploaded_file kommando.

if (empty($errors)) {
  move_uploaded_file($file_tmp, $file);
}

Nu kan vi lukke for loop, og udskriv fejlene. Dette vil blive vist for os på netværksfanen, vi brugte før for at se output af $_FILES .

if ($errors) print_r($errors);

Sæt det hele sammen, og her er process.php .

process.php
<?php

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (isset($_FILES['files'])) {
        $errors = [];
        $path = 'uploads/';
        $extensions = ['jpg', 'jpeg', 'png', 'gif'];

        $all_files = count($_FILES['files']['tmp_name']);

        for ($i = 0; $i < $all_files; $i++) {
            $file_name = $_FILES['files']['name'][$i];
            $file_tmp = $_FILES['files']['tmp_name'][$i];
            $file_type = $_FILES['files']['type'][$i];
            $file_size = $_FILES['files']['size'][$i];
            $file_ext = strtolower(end(explode('.', $_FILES['files']['name'][$i])));

            $file = $path . $file_name;

            if (!in_array($file_ext, $extensions)) {
                $errors[] = 'Extension not allowed: ' . $file_name . ' ' . $file_type;
            }

            if ($file_size > 2097152) {
                $errors[] = 'File size exceeds limit: ' . $file_name . ' ' . $file_type;
            }

            if (empty($errors)) {
                move_uploaded_file($file_tmp, $file);
            }
        }

        if ($errors) print_r($errors);
    }
}

Test det nu. Hvis du bruger formularen til at uploade nogle filer, kan du se dem i uploads folder. Hvis du prøver at uploade en fil, der er for stor eller af den forkerte type, vil du se fejlene i Netværket svar.

Konklusion

Tillykke, du har oprettet en fungerende uploadformular. Dette er en spændende lille proces, hvis du aldrig har uploadet en fil eller brugt $_FILES superglobal før.

Den komplette kilde er på GitHub.

  • Se kilde på GitHub

Bemærk, at dette ikke er en komplet, sikker produktionsproces. Her er et par ting, du skal tage i betragtning:

  • Der er ingen JavaScript-sidevalidering. Brugeren skal have vist en fejl på frontend, hvis deres fil er af den forkerte type, før de indsender.
  • Beskæftiger sig med flere filer med samme navn.
  • Denne metode til fejlhåndtering er kun til udviklingsprocessen.

Tak fordi du læste med. Jeg kan også lave en om at uploade til Amazon S3 og/eller DigitalOcean Spaces, hvis der er interesse.