JavaScript >> Javascript 文檔 >  >> Tags >> PHP

如何使用純 JavaScript 和 PHP 將文件上傳到服務器

從頭開始編寫將圖像上傳到服務器的代碼似乎是一項非常艱鉅的任務。我將製作一個非常簡單的上傳表單來演示文件數據的工作原理和傳輸方式。

在本教程中,我們將使用 HTML 構建一個上傳表單 , 用 JavaScript 發送文件 ,並使用 PHP 處理和上傳它們 .

請注意,這並不意味著功能齊全、安全、經過驗證的生產代碼。它只是為了以簡單明了的方式演示如何製作您的第一個上傳表單。

  • 在 GitHub 上查看源代碼

先決條件

  • HTML 基礎知識
  • PHP語法和代碼結構的基本知識
  • 了解本地 PHP 環境。如果您不知道這意味著什麼,請閱讀本指南,了解如何設置 MAMP 環境。

目標

  • 使用 HTML 構建最簡單的表單以從本地計算機獲取文件。
  • 使用原生 JavaScript 將數據從 HTML 表單發送到 PHP 腳本。
  • 處理 PHP 腳本中的數據並將本地文件移動到 uploads/ 服務器上的目錄。

設置

如先決條件所述,您必須具備 PHP 和本地服務器環境的基本知識。

如果您使用的是 Mac,則可以使用單個命令創建服務器。要對此進行測試,請創建一個名為 test.php 的文件 在您選擇的目錄中。我將創建一個名為 local 的目錄 .完整路徑將是 Users/tania/local .

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

在終端應用程序中,我將通過按 SPACEBAR 打開它 + COMMAND 並輸入終端,導航到您在其中創建文件的目錄。

cd server
php -S localhost:8888

您現在應該可以訪問 http://localhost:8888/test.php 並查看代碼的輸出。

如果您使用的是 Windows,或者您不想使用命令行,請設置 MAMP。

在 HTML 中構建上傳表單

在本地服務器的根目錄中,創建一個 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 goes here-->
  </body>
</html>

讓我們在 body 中添加一個 HTML Web 表單 .

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

在這種形式中,我們使用 POST HTTP 方法,我們如何發送數據。 multipart/form-data 在表單中上傳文件時需要 value。

從這裡開始,我們創建了一個文件輸入類型,它接受一個文件數組(files[] ) 我們指定 multiple 允許選擇多個文件。 files[] 可以有任何名字 - 你可以使用 uploads[]images[] ,但我稱之為 files[] 為簡單起見。

最後,我們有一個提交按鈕。由於下一步將添加一個腳本,因此我們只需添加一個指向我們將創建的 JavaScript 文件的鏈接。

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

這就是我們所需要的視圖。

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>

通過 JavaScript 發送表單數據

現在,單擊表單上的提交不會去任何地方。因為我們沒有 action 導致 URL,默認情況下,表單只會發佈到自身。由於 index.html 是一個 html 文件,而不是一個 PHP 文件,在這個頁面上不能進行任何表單處理。相反,我們將通過 JavaScript 將表單發送到 PHP。

創建一個名為 upload.js 的文件 .

首先,讓我們定義兩個變量——我們要發送數據的 URL,以及表單的 DOM 元素。

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

我們將添加一個事件偵聽器來監視正在提交的表單,但我們會阻止觸發默認操作。

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

  // ...
})

讓我們用 .files 收集文件 屬性,並開始一個新的 FormData() 界面。

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

// ...

對於已提交的每個文件,將其附加到 files[] 數組。

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

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

// ...

最後,使用內置的 Fetch API 將數據 POST 到我們指定的 URL。將響應打印到控制台(用於測試目的)。

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

這是完成的 upload.js .

上傳.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)
  })
})

現在 - 我們如何測試所有這些數據是否正確通過?讓我們打印出文件數據。

創建一個名為 process.php 的新文件 , 並打印出超全局數組 $_FILES 的內容 ,其中將包含我們所有文件的數據。

進程.php
<?php print_r($_FILES);

獲得此文件後,嘗試通過表單上傳一些文件。我做了一個 phplogo.pngtestfile1.txt 進行測試,並上傳文件。

在開發者工具中,控制台下 ,您應該會看到這樣的響應:

開發者工具 -> 控制台

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

如果您看到 status: 200 ,這意味著文件點擊了正確的 URL 並且 URL 存在。

現在在開發者工具中,點擊 Network 標籤。您應該看到文件名 process.php .單擊文件,然後單擊響應 .在那裡,您應該看到 print_r($FILES) 的輸出 .它看起來像這樣:

開發者工具 -> 網絡 -> 響應

[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
  )
)

現在我們知道正確的文件及其所有相關數據已通過。成功!

用 PHP 處理表單數據

現在我們正在收集表單中的所有文件並將它們發送到 process.php 使用 JavaScript,我們必須使用 PHP 移動文件數據。

首先,我們要確保代碼僅在 POST 請求命中文件時運行。

進程.php
<?php

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

我們還想確保文件已經通過。

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

在項目的根目錄中創建一個名為 uploads 的目錄 .這個目錄需要有 755 接受傳入文件的權限。

此時,我們將為錯誤創建一個數組,設置上傳的目錄路徑,並設置允許的擴展。

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

由於用戶可以上傳多個文件,我們將創建一個 $all_files 變量,獲取上傳文件的數量,並製作一個for 循環。

$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;

現在我們可以為文件設置一些規則。如果文件類型不在允許的擴展名列表中,或者文件太大,我們會將其添加到錯誤數組中。我將文件大小設置為 2 兆字節。

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;
}

如果沒有錯誤,我們可以繼續將文件移動到 uploads move_uploaded_file 的文件夾 命令。

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

現在我們可以關閉 for 循環,並打印出錯誤。這將顯示在我們之前使用的網絡選項卡中,以查看 $_FILES 的輸出 .

if ($errors) print_r($errors);

把它們放在一起,這裡是 process.php .

進程.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);
    }
}

現在測試一下。如果您使用表單上傳一些文件,您會在上傳中看到它們 文件夾。如果您嘗試上傳過大或類型錯誤的文件,您會在網絡中看到錯誤 回應。

結論

恭喜,您已經成功創建了一個正常工作的上傳表單。如果您從未成功上傳文件或使用過 $_FILES,這是一個令人興奮的小過程 之前的超全球。

完整源碼在 GitHub 上。

  • 在 GitHub 上查看源代碼

請注意,這不是一個完整、安全的生產過程。以下是一些需要考慮的事項:

  • 沒有 JavaScript 端驗證。如果用戶在提交前文件類型錯誤,則應在前端向用戶顯示錯誤。
  • 處理多個同名文件。
  • 此錯誤處理方法僅適用於開發過程。

謝謝閱讀。如果有興趣,我也可以製作一個關於上傳到 Amazon S3 和/或 DigitalOcean Spaces 的內容。


Tutorial JavaScript 教程
  1. 開始一個新的蓋茨比項目

  2. 如何在 JavaScript 中將時間四捨五入到最接近的一刻鐘?

  3. 在 VS 代碼中更改光標顏色🤯

  4. jQTouch 讓 iPhone 和 iPod Touch 上的 Web 開髮變得輕而易舉

  5. DOM 事件優先級

  6. Package.json 與 Package-lock.json 與 Npm-shrinkwrap.json

  7. Javascript Regex-用相同數量的另一個字符替換字符序列

  1. 構建後端 |節點、Postgres、GraphQL

  2. JavaScript 過濾器函數解釋

  3. 反應檢測div到達頂部和底部

  4. 理解排序()

  5. 如何判斷網頁資源何時被緩存?

  6. 方便的 JS 方法和實用函數

  7. 畫一條總是和它的父 BoxElement 一樣寬的線?

  1. 使用 AWS Lambda 和 Twilio 發送天氣預報

  2. 如何使用 Next.js 變魔術

  3. Jmeter – 通過 JavaScript 發送帶有文件的表單

  4. 在 Hostinger 上為 React App 創建部署管道