Chapterبەش 8 · Lectureوانە 8.7

Uploading Filesبارکردنی فایل

Let visitors upload pictures safely: the upload form and php.ini, the temporary folder and $_FILES, checks for errors, size, extension and real type that really block bad files, move_uploaded_file(), safe storage, and the BLOB method with prepared statements.

ڕێگە بدە سەردانکەران بە سەلامەتی وێنە بار بکەن: و ⁦php.ini⁩، کاتی و ⁦$_FILES⁩، پشکنینی و قەبارە و و جۆری ڕاستەقینە کە بە ڕاستی خراپ ڕادەگرن، ⁦move_uploaded_file()⁩، هەڵگرتنی سەلامەت و ڕێگای BLOB بە .

37 min read34 خولەک خوێندنەوە · 31 stepsهەنگاو

What you will learnچی فێر دەبیت

  • Build an upload form with the right method, enctype and field name, and configure php.ini.
  • Explain the journey of an upload: temporary folder, $_FILES, checks, move_uploaded_file().
  • Read every key of $_FILES and know which values can be trusted.
  • Check the error code, size, extension and real type so that every failed check blocks the upload.
  • Store uploads safely: unique names, outside the web root or with scripts blocked.
  • Store a file in a database BLOB column with a prepared statement.
  • دروست بکەیت بە method و enctype و ناوی دروستی و ⁦php.ini⁩ ڕێکبخەیت.
  • ڕێگای ڕوون بکەیتەوە: کاتی، ⁦$_FILES⁩، پشکنینەکان، ⁦move_uploaded_file()⁩.
  • هەموو ⁦$_FILES⁩ بخوێنیتەوە و بزانیت کام جێی متمانەیە.
  • کۆدی ، قەبارە، و جۆری ڕاستەقینە بپشکنیت بە شێوەیەک کە هەر پشکنینێکی شکستخواردوو ڕابگرێت.
  • بارکراوەکان بە سەلامەتی هەڵبگریت: ناوی بێهاوتا، لە دەرەوەی ڕەگی وێب یان بە ڕاگرتنی .
  • لە BLOBـی بە هەڵبگریت.

Why file uploads need careبۆچی بارکردنی فایل وردبینی دەوێت

Many websites let visitors send a file: a profile photo, a homework PDF, a picture of a product. Sending a file from the visitor's computer to the server is called . In PHP it takes a special , the $_FILES , and the move_uploaded_file().

زۆر ڕێگە بە سەردانکەران دەدەن بنێرن: وێنەی پرۆفایل، PDFـی ئەرکی ماڵەوە، وێنەی کاڵایەک. ناردنی لە سەردانکەرەوە بۆ پێی دەوترێت . لە PHPـدا پێویستی بە تایبەت، $_FILES و move_uploaded_file() هەیە.

Uploads are useful, but they are also one of the riskiest features of a website: a stranger puts a whole file on your server. If you keep any file that arrives, someone can fill your disk, overwrite other people's files, or upload a PHP program and run it on your server. This lecture first builds the upload step by step, as the course does, and then makes it safe.

بەسوودە، بەڵام یەکێکە لە مەترسیدارترین تایبەتمەندییەکانی : کەسێکی نەناسراو تەواو لەسەر دادەنێت. ئەگەر هەر گەیشت هەڵیبگریت، کەسێک دەتوانێت دیسکەکەت پڕ بکات، خەڵکی تر بسڕێتەوە و جێیان بگرێتەوە، یان PHP بار بکات و لەسەر جێبەجێی بکات. ئەم وانەیە سەرەتا وەک کۆرسەکە هەنگاو بە هەنگاو دروست دەکات و پاشان سەلامەتی دەکات.

The parcel room at the post officeژووری بەستەکان لە پۆستەخانە

When a parcel arrives at the post office, it does not go straight to the shelves. It waits in a parcel room under a temporary number. A clerk checks it: is the address right, is it too heavy, is it really what the label says? Only then does it get a proper place on a shelf. Parcels that nobody takes are thrown away at the end of the day. An upload works the same way: PHP keeps the file in a temporary folder, your script is the clerk that checks it, and move_uploaded_file() puts it on the shelf.

کاتێک بەستەیەک دەگاتە پۆستەخانە، ڕاستەوخۆ ناچێتە سەر ڕەفەکان. لە ژووری بەستەکاندا بە ژمارەیەکی کاتی چاوەڕێ دەکات. فەرمانبەرێک دەیپشکنێت: ئایا ناونیشانەکەی ڕاستە، ئایا زۆر قورسە، ئایا بە ڕاستی ئەوەیە کە لەسەر لیبڵەکەی نووسراوە؟ تەنها دوای ئەوە شوێنێکی ڕاستەقینەی لەسەر ڕەفێک پێدەدرێت. ئەو بەستانەی کەس نایانبات لە کۆتایی ڕۆژدا فڕێ دەدرێن. بە هەمان شێوە کار دەکات: PHP لە کاتیدا ڕادەگرێت، ئەو فەرمانبەرەیە کە دەیپشکنێت و move_uploaded_file() دەیخاتە سەر ڕەفەکە.

Where the analogy stops workingسنووری ئەم نموونەیە

A post-office clerk checks every parcel by habit. PHP does not check anything by itself, not even for viruses. If your script does not check the file, nobody does.

فەرمانبەری پۆستەخانە بە خوو هەموو بەستەیەک دەپشکنێت. بەڵام PHP خۆی هیچ شتێک ناپشکنێت، تەنانەت ڤایرۆسیش. ئەگەر نەپشکنێت، کەس نایپشکنێت.

Quick checkپشکنینی خێراWho checks an uploaded file before it is kept?کێ بارکراو پێش هەڵگرتنی دەپشکنێت؟

List of All Basic PHP Security You Need to Know | PHP Security for Beginners | PHP Security LessonDani Krossing · Englishئینگلیزی · 41K viewsبینین · 1.6K likesلایک · Partبەشی 6:32–8:46 (ofلە 19:07)

Explains why accepting files from visitors is dangerous and which basic checks keep your website safe.

ڕوون دەکاتەوە بۆچی وەرگرتنی لە سەردانکەران مەترسیدارە و کام پشکنینە سەرەتاییانە پارێزراو دەهێڵنەوە.

Watch 6:32–8:46: the file upload security chapter.

لە ⁦6:32⁩ تا ⁦8:46⁩ سەیر بکە: بەشی .

What you need before you startئەوەی پێش دەستپێکردن پێویستتە

To upload a file to the server with <input type="file">, take care of these points:

بۆ بۆ بە <input type="file">، ئاگات لەم خاڵانە بێت:

  1. Always use the to send the form: method="post". A file cannot travel in the URL.
  2. Add the enctype="multipart/form-data" to the <form> tag. Without this attribute, the file is not uploaded: PHP receives only its name.
  3. Give the file input a name; PHP finds the file by that name in $_FILES.
  4. Make sure that PHP allows uploads: in , the directive file_uploads must be On.
  1. هەمیشە بە بنێرە: method="post". ناتوانێت لە ناو URLـدا بگوازرێتەوە.
  2. enctype="multipart/form-data" بۆ <form> زیاد بکە. بەبێ ئەم بار ناکرێت: PHP تەنها ناوەکەی وەردەگرێت.
  3. ناوێک (name) بدە بە ؛ PHP بەو ناوە لە $_FILESدا دەدۆزێتەوە.
  4. دڵنیابە کە PHP ڕێگە بە دەدات: لە ، ڕێنمایی file_uploads دەبێت On بێت.
upload formHTMLRuns in the browserلە ناو تۆڕگەڕ کار دەکات
<form action="index.php" method="post" enctype="multipart/form-data">
  Select image to upload:
  <input type="file" name="image" id="fileToUpload">
  <input type="submit" value="Upload Image" name="submit">
</form>
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 1

method="post" and enctype="multipart/form-data" are both required. action names the PHP file that receives the upload.

هەردووکی method="post" و enctype="multipart/form-data" پێویستن. action ناوی ئەو PHPـیە کە وەردەگرێت.

Lineدێڕی 3

PHP uses the name (image), not the id.

PHP ناوەکە (name، واتە image) بەکار دەهێنێت، نەک id.

The course deck shows a shorter form with no action (the form posts back to the same page) and a field called photo:

کۆرسەکە کورتتر پیشان دەدەن بەبێ action ( دەنێردرێتەوە بۆ هەمان لاپەڕە) و بە ناوی photo:

An upload formفۆرمێکی بارکردنHTMLRuns in the browserلە ناو تۆڕگەڕ کار دەکات
<form method="post" enctype="multipart/form-data">
  <input type="file" name="photo">
  <input type="submit">
</form>
Quick checkپشکنینی خێراWhich two form attributes are required for a file upload?کام دوو بۆ پێویستن؟

What you need before you startئەوەی پێش دەستپێکردن پێویستتە

Configure the php.ini fileفایلی ⁦php.ini⁩ ڕێکبخە

First, ensure that PHP is configured to allow file uploads. In your php.ini file (in XAMPP: C:\xampp\php\php.ini), search for the file_uploads directive and set it to On:

سەرەتا دڵنیابە کە PHP ڕێکخراوە بۆ ئەوەی ڕێگە بە بدات. لە php.iniـەکەتدا (لە XAMPPـدا: C:\xampp\php\php.ini)، بەدوای ڕێنمایی file_uploadsدا بگەڕێ و بیکە بە On:

php.iniINI
file_uploads = On

On is already the default. Three more settings limit the size and number of uploads. After changing php.ini, restart Apache in the XAMPP Control Panel.

On پێشتر بنەڕەتییە. سێ تر قەبارە و ژمارەی سنووردار دەکەن. دوای گۆڕینی php.ini، Apache لە XAMPPـدا دابخە و دووبارە هەڵیبکەرەوە.

Upload settings in php.ini لە ⁦php.ini⁩
DirectiveڕێنماییPHP's defaultبنەڕەتی PHPMeaningواتا
file_uploadsOnAllow uploads at all.ڕێگەدان بە بە گشتی.
upload_max_filesize2MThe largest single file. A bigger file arrives with error code 1.گەورەترین تاکە . گەورەتر بە کۆدی 1 دەگات.
post_max_size8MThe largest whole request (all fields and files). Bigger: PHP empties $_POST and $_FILES.گەورەترین تەواو (هەموو و ). گەورەتر: PHP $_POST و $_FILES بەتاڵ دەکات.
max_file_uploads20The most files in one request.زۆرترین ژمارەی لە یەک .
limits.phpPHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
echo "file_uploads: " . ini_get("file_uploads") . "\n";
echo "upload_max_filesize: " . ini_get("upload_max_filesize") . "\n";
echo "post_max_size: " . ini_get("post_max_size") . "\n";
echo "max_file_uploads: " . ini_get("max_file_uploads") . "\n";

Two ways to keep an uploaded fileدوو ڕێگا بۆ هەڵگرتنی فایلی بارکراو

The course names two methods for storing uploaded files:

کۆرسەکە ناوی دوو ڕێگا دەهێنێت بۆ هەڵگرتنی بارکراوەکان:

  1. Copy the file to a local folder and store its path in the database. The file sits in a folder such as Uploads/; the keeps only its name or path.
  2. Store the file itself in the database as a (Binary Large Object): the bytes of the file go into a column of type LONGBLOB.
  1. بۆ ناوخۆیی کۆپی بکە و لە هەڵبگرە. لە وەک Uploads/دایە؛ تەنها ناو یان هەڵدەگرێت.
  2. خۆی لە وەک هەڵبگرە ⁦(Binary Large Object)⁩: دەچنە ناو لە جۆری LONGBLOB.
A tree with the root "File upload methods" and two branches. Method 1: copy the file to a folder and store its path in the database; an Uploads/ folder holds files with random names and a photos table holds rows of id and path; the usual choice, the database stays small and pictures load fast; uses move_uploaded_file(). Method 2: store the file itself in the database as a BLOB; an uploads table has id, name and a LONGBLOB data column with the file's bytes; everything in one place but the database grows big and slow; uses file_get_contents() and INSERT.دارێک بە ڕەگی «ڕێگاکانی بارکردنی فایل» و دوو لق. ڕێگای ١: فایلەکە بۆ فۆڵدەرێک کۆپی بکە و ڕێڕەوەکەی لە بنکەدراوەدا هەڵبگرە؛ فۆڵدەری Uploads/ فایل بە ناوی هەڕەمەکی هەڵدەگرێت و خشتەی photos ڕیزی id و path هەڵدەگرێت؛ هەڵبژاردنی باو، بنکەدراوەکە بچووک دەمێنێتەوە و وێنەکان خێرا دەکرێنەوە؛ move_uploaded_file() بەکار دەهێنێت. ڕێگای ٢: فایلەکە خۆی لە بنکەدراوەدا وەک BLOB هەڵبگرە؛ خشتەی uploads ستوونەکانی id و name و data ـی LONGBLOB ـی هەیە کە بایتەکانی فایلەکەی تێدایە؛ هەموو شتێک لە یەک شوێندایە بەڵام بنکەدراوەکە گەورە و خاو دەبێت؛ file_get_contents() و INSERT بەکار دەهێنێت.
The two upload methods from the course, with their main advantage and cost.دوو ڕێگاکەی لە کۆرسەکەوە، لەگەڵ سوودی سەرەکی و تێچووی هەر یەکێکیان.CêIT

Method 1 is the usual recommendation, and most of this lecture builds it (the slides show it in five steps). Method 2 is shown at the end, in Storing the file in the database (BLOB).

ڕێگای ١ ئامۆژگاریی باوە و زۆربەی ئەم وانەیە ئەو دروست دەکات ( لە پێنج هەنگاودا پیشانی دەدەن). ڕێگای ٢ لە کۆتاییدا پیشان دراوە، لە هەڵگرتنی فایل لە بنکەدراوەدا ⁦(BLOB)⁩.

Quick checkپشکنینی خێراWhich method keeps the database small and is the usual choice?کام ڕێگا بچووک دەهێڵێتەوە و هەڵبژاردنی باوە؟

Where the file goes: the temporary folderفایلەکە بۆ کوێ دەچێت: فۆڵدەری کاتی

The journey of an upload in four steps. 1: the browser sends a form with method post and enctype multipart/form-data containing cat.png. 2: PHP keeps the file in a temporary folder such as /tmp/phpA1b2C3 and describes it in $_FILES['image'] with name, type, size, tmp_name, error and full_path. 3: your checks: error equals UPLOAD_ERR_OK, the size is not too big, the extension is allowed, the real type found with finfo is allowed. If all are OK, 4: move_uploaded_file() moves it to the Uploads folder under a new random name. If there is a problem, show an error message. A dashed arrow from step 2 says: not moved? When the script ends, PHP deletes the temporary file by itself. A note says PHP does not scan files for viruses; the checks are your job, and you must never trust the name or type that the browser sends.ڕێگای بارکردنێک لە چوار هەنگاودا. ١: تۆڕگەڕ فۆرمێک بە method post و enctype multipart/form-data دەنێرێت کە cat.pngی تێدایە. ٢: PHP فایلەکە لە فۆڵدەرێکی کاتیدا وەک /tmp/phpA1b2C3 ڕادەگرێت و لە $_FILES['image']دا بە name و type و size و tmp_name و error و full_path وەسفی دەکات. ٣: پشکنینەکانی تۆ: error یەکسانە بە UPLOAD_ERR_OK، قەبارەکە زۆر گەورە نییە، پاشگری فایلەکە ڕێگەپێدراوە، جۆرە ڕاستەقینەکە کە بە finfo دۆزراوەتەوە ڕێگەپێدراوە. ئەگەر هەمووی باش بوو، ٤: move_uploaded_file() دەیگوازێتەوە بۆ فۆڵدەری Uploads بە ناوێکی نوێی هەڕەمەکی. ئەگەر کێشەیەک هەبوو، هەڵەنامە پیشان بدە. تیرێکی پچڕپچڕ لە هەنگاوی ٢ەوە دەڵێت: نەگوازرایەوە؟ کاتێک دەسنووسەکە تەواو دەبێت PHP خۆی فایلە کاتییەکە دەسڕێتەوە. تێبینییەک دەڵێت PHP فایلەکان بۆ ڤایرۆس ناپشکنێت؛ پشکنینەکان ئەرکی تۆن و هەرگیز نابێت متمانە بەو ناو و جۆرە بکەیت کە تۆڕگەڕ دەینێرێت.
The journey of an uploaded file: browser, temporary folder, your checks, and the final folder.ڕێگای بارکراو: ، کاتی، پشکنینەکانی تۆ و کۆتایی.CêIT

When a form with a file arrives, PHP does not put the file where you want it. It saves it in a temporary folder (set by upload_tmp_dir in php.ini, or the system's temp folder) under a random name, for example /tmp/phpA1b2C3. Then it fills $_FILES with information about the file and runs your script.

کاتێک بە دەگات، PHP لەو شوێنەدا دانانێت کە تۆ دەتەوێت. لە کاتیدا بە ناوێکی هەڕەمەکی خەزنی دەکات، بۆ نموونە /tmp/phpA1b2C3 (ئەو بە upload_tmp_dir لە php.iniدا دیاری دەکرێت، یان کاتیی سیستەمەکەیە). پاشان $_FILES بە زانیاری دەربارەی پڕ دەکاتەوە و جێبەجێ دەکات.

This is a holding area. Your script looks at it and decides: keep it (move it with move_uploaded_file()) or not. If the script does not move it, PHP deletes the temporary file automatically when the request ends. So a rejected file simply disappears.

شوێنێکی ڕاگرتنە. سەیری دەکات و بڕیار دەدات: هەڵیبگرێت (بە move_uploaded_file() بیگوازێتەوە) یان نا. ئەگەر نەیگوازێتەوە، PHP لە کۆتایی خۆی دەسڕێتەوە. بۆیە ڕەتکراوە بە سادەیی ون دەبێت.

Quick checkپشکنینی خێراYour script checks the file but never calls move_uploaded_file(). What happens to the uploaded file? دەپشکنێت بەڵام هەرگیز move_uploaded_file() بانگ ناکات. چی بەسەر بارکراوەکەدا دێت؟

$_FILES: what PHP tells you about the file⁦$_FILES⁩: ئەوەی PHP دەربارەی فایلەکە پێت دەڵێت

The $_FILES superglobal holds information about the files that arrived with a POST request. For each file input it has an with six . $_FILES itself does not upload anything; the browser and PHP did that before your script started. Here is what PHP filled in when we uploaded cat.png through the form above:

$_FILES زانیاری دەربارەی ئەو هەڵدەگرێت کە لەگەڵ POST گەیشتوون. بۆ هەر بە شەش هەیە. $_FILES خۆی هیچ شتێک بار ناکات؛ و PHP پێش دەستپێکردنی ئەو کارەیان کردووە. ئەمە ئەوەیە کە PHP پڕی کردەوە کاتێک cat.pngمان لە ڕێگەی سەرەوە بار کرد:

show-files.phpPHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
echo "<pre>";
print_r($_FILES);
echo "</pre>";
The six keys of $_FILES['image']شەش ⁦$_FILES['image']⁩
KeyWhat it holdsچی تێدایەCan you trust it?دەتوانیت متمانەی پێ بکەیت؟
nameThe original file name on the visitor's computer, e.g. cat.png.ناوی ڕەسەنی لەسەر سەردانکەر، بۆ نموونە cat.png.No: the visitor chooses it.نەخێر: سەردانکەر هەڵیدەبژێرێت.
full_pathThe name with any folder part the browser sent (PHP 8.1+).ناوەکە لەگەڵ هەر بەشێکی کە ناردبێتی (⁦PHP 8.1⁩ و دواتر).No.نەخێر.
typeThe that the browser claims, e.g. image/png.، بەو شێوەیەی دەیڵێت، بۆ نموونە image/png.No: it can be faked.نەخێر: دەکرێت ساختە بکرێت.
tmp_nameThe path of the temporary file on the server. لەسەر .Yes: PHP made it.بەڵێ: PHP دروستی کردووە.
errorAn error code; 0 (UPLOAD_ERR_OK) means the upload worked.کۆدێکی ؛ 0 (UPLOAD_ERR_OK) واتە سەرکەوتوو بوو.Yes.بەڵێ.
sizeThe size in bytes.قەبارەکە بە .Yes: PHP measured it.بەڵێ: PHP پێوانەی کردووە.

The deck's short example reads three of them:

نموونە کورتەکەی سێیان دەخوێنێتەوە:

read.phpPHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
if (isset($_FILES["photo"])) {
    echo $_FILES["photo"]["name"] . "<br>";
    echo $_FILES["photo"]["size"] . "<br>";
    echo $_FILES["photo"]["type"] . "<br>";
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 2

Only read $_FILES when a file was really sent.

تەنها کاتێک $_FILES بخوێنەوە کە بە ڕاستی نێردرابێت.

Quick checkپشکنینی خێراWhich value in $_FILES['image'] can you trust?کام لە $_FILES['image']دا دەتوانیت متمانەی پێ بکەیت؟

PHP File Uploads - Full PHP 8 TutorialProgram With Gio · Englishئینگلیزی · 29K viewsبینین · 1K likesلایک · Partبەشی 0:05–2:39 (ofلە 8:32)

Shows the upload form and what the $_FILES array holds for an uploaded file: its name, type, temporary name, error and size.

پیشان دەدات و ئەوەی $_FILES بۆ بارکراو هەڵیدەگرێت: ناو، جۆر، ناوی کاتی، و قەبارەکەی.

Watch 0:05–2:39: the upload form and what $_FILES holds.

لە ⁦0:05⁩ تا ⁦2:39⁩ سەیر بکە: و ئەوەی $_FILES تێیدایە.

$_FILES: what PHP tells you about the file⁦$_FILES⁩: ئەوەی PHP دەربارەی فایلەکە پێت دەڵێت

Upload error codesکۆدەکانی هەڵەی بارکردن

The error key always holds one of these numbers. PHP gives each number a name (a constant), so you can write UPLOAD_ERR_OK instead of 0:

error هەمیشە یەکێک لەم ژمارانەی تێدایە. PHP ناوێک () دەدات بە هەر ژمارەیەک، بۆیە دەتوانیت لە جیاتی 0 بنووسیت UPLOAD_ERR_OK:

Values of $_FILES['image']['error'] ⁦$_FILES['image']['error']⁩
ConstantValueMeaningواتا
UPLOAD_ERR_OK0No error: the file arrived.هیچ نییە: گەیشت.
UPLOAD_ERR_INI_SIZE1Bigger than upload_max_filesize in php.ini.گەورەترە لە upload_max_filesize لە ⁦php.ini⁩دا.
UPLOAD_ERR_FORM_SIZE2Bigger than a MAX_FILE_SIZE field in the form.گەورەترە لە MAX_FILE_SIZE لە .
UPLOAD_ERR_PARTIAL3Only part of the file arrived.تەنها بەشێکی گەیشت.
UPLOAD_ERR_NO_FILE4No file was chosen.هیچ هەڵنەبژێردرا.
UPLOAD_ERR_NO_TMP_DIR6The temporary folder is missing. کاتی نییە.
UPLOAD_ERR_CANT_WRITE7The file could not be written to disk. نەتوانرا لەسەر دیسک بنووسرێت.
UPLOAD_ERR_EXTENSION8A PHP extension stopped the upload. PHP ڕاگرت.

Step 1: read the file's informationهەنگاوی ١: زانیارییەکانی فایلەکە بخوێنەوە

The course builds the upload script step by step. The first step checks whether the user clicked submit and puts each piece of information about the file into a . Here is that step, corrected, with a few echo lines so that you can see the values. We uploaded a photo called Erbil Photo.JPG:

کۆرسەکە هەنگاو بە هەنگاو دروست دەکات. هەنگاوی یەکەم دەپشکنێت ئایا کرتەی لە ناردن کردووە و هەر پارچە زانیارییەک دەربارەی دەخاتە ناو . ئەمە ئەو هەنگاوەیە، ڕاستکراوە، لەگەڵ چەند دێڕێکی echo بۆ ئەوەی ببینیت. وێنەیەکمان بە ناوی Erbil Photo.JPG بار کرد:

index.php (step 1)PHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
if (isset($_POST["submit"])) {                        // did the user click the submit button?
    $target_dir = "Uploads/";                         // the folder where files are saved
    $errors = [];                                     // collects error messages
    $file_name = basename($_FILES["image"]["name"]);  // the file's original name
    $file_size = $_FILES["image"]["size"];            // its size in bytes
    $file_tmp  = $_FILES["image"]["tmp_name"];        // where PHP keeps it for now
    $file_type = $_FILES["image"]["type"];            // type sent by the browser: do not trust it
    $file_ext  = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));  // e.g. "jpg"
    $target_file = $target_dir . $file_name;          // the path we plan to save to
    $extensions = ["jpeg", "jpg", "png"];             // allowed extensions

    echo "Name: $file_name<br>";
    echo "Size: $file_size bytes<br>";
    echo "Temporary file: $file_tmp<br>";
    echo "Type (from the browser): $file_type<br>";
    echo "Extension: $file_ext<br>";
    echo "Target: $target_file<br>";
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 2

Check if the user clicked submit. Everything else is inside this if, so a normal visit does not touch $_FILES.

بپشکنە ئایا کرتەی لە ناردن کردووە. هەموو شتێکی تر لەناو ئەم ifـەدایە، بۆیە سەردانێکی ئاسایی دەست لە $_FILES نادات.

Lineدێڕی 3

The folder where the file should be saved. It must exist; the name is case-sensitive on Linux (Uploads is not uploads).

ئەو دەبێت تێیدا خەزن بکرێت. دەبێت هەبێت؛ لەسەر Linux ناوەکە هەستیارە بە پیتی گەورە و بچووک (Uploads هەمان uploads نییە).

Lineدێڕی 4

Collects error messages (an empty array).

کۆ دەکاتەوە ( بەتاڵ).

Lineدێڕی 5

Get the file name. basename() removes any folder part.

ناوی وەربگرە. basename() هەر بەشێکی لادەبات.

Lineدێڕی 6

Get the selected file's size in bytes.

قەبارەی هەڵبژێردراوەکە بە وەربگرە.

Lineدێڕی 7

Get the temporary file name.

ناوی وەربگرە.

Lineدێڕی 8

Get the file type, as the browser reports it.

وەربگرە، وەک دەیڵێت.

Lineدێڕی 9

Get the file extension in lower case.

بە پیتی بچووک وەربگرە.

Lineدێڕی 10

Build the path where the file will be saved. This line only builds a string; move_uploaded_file() saves the file later.

ئەو دروست بکە کە تێیدا خەزن دەکرێت. ئەم دێڕە تەنها دروست دەکات؛ دواتر move_uploaded_file() خەزن دەکات.

Lineدێڕی 11

The array of allowed extensions.

کە ڕێگەپێدراون.

Step 1: read the file's informationهەنگاوی ١: زانیارییەکانی فایلەکە بخوێنەوە

Getting the extension: pathinfo() instead of end(explode())وەرگرتنی پاشگری فایل: ⁦pathinfo()⁩ لە جیاتی ⁦end(explode())⁩

The course gets the extension with strtolower(end(explode('.', $name))). explode() breaks a string into an array at each dot; end() takes the last element; strtolower() makes it lower case:

کۆرسەکە بە strtolower(end(explode('.', $name))) وەردەگرێت. explode() لە هەر خاڵێکدا دەشکێنێت بۆ ؛ end() کۆتا وەردەگرێت؛ strtolower() دەیکاتە پیتی بچووک:

PHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
print_r(explode('.', "my.cat.png"));

But end() needs a real variable, because it moves the array's internal pointer. Given the result of a function directly, PHP 7 and 8 print a notice:

بەڵام end() پێویستی بە ڕاستەقینە هەیە، چونکە ئاماژەی ناوەکیی دەجووڵێنێت. ئەگەر ڕاستەوخۆ ئەنجامی پێبدرێت، ⁦PHP 7⁩ و 8 ئاگادارییەک چاپ دەکەن:

extension.phpPHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
$file_ext = strtolower(end(explode('.', "photo.png")));
echo $file_ext;

Use pathinfo() instead; it was made for this job. (Or store the parts in a variable first, as the second line of this example does.)

لە جیاتی ئەوە pathinfo() بەکاربهێنە؛ بۆ ئەم کارە دروست کراوە. (یان سەرەتا پارچەکان لە هەڵبگرە، وەک دێڕی دووەمی ئەم نموونەیە دەیکات.)

PHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
$name = "Holiday.Photo.JPG";
$parts = explode('.', $name);          // ["Holiday", "Photo", "JPG"]
echo strtolower(end($parts)), "<br>";  // jpg
echo strtolower(pathinfo($name, PATHINFO_EXTENSION)), "<br>";  // jpg
echo "[" . pathinfo("README", PATHINFO_EXTENSION) . "]";       // no dot: empty
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 5

A name without a dot has no extension: pathinfo() returns an empty string. (The end(explode()) way would return the whole name, readme.)

ناوێک بەبێ خاڵ هیچ نییە: pathinfo() بەتاڵ دەگەڕێنێتەوە. (ڕێگای end(explode()) هەموو ناوەکە دەگەڕێنێتەوە، readme.)

Quick checkپشکنینی خێراWhat does pathinfo("Holiday.Photo.JPG", PATHINFO_EXTENSION) return?pathinfo("Holiday.Photo.JPG", PATHINFO_EXTENSION) چی دەگەڕێنێتەوە؟

Step 1: read the file's informationهەنگاوی ١: زانیارییەکانی فایلەکە بخوێنەوە

basename(): the file name from a path⁦basename()⁩: ناوی فایل لە ڕێڕەوێکەوە

The basename() function gets the file name from a . It takes the path as an and returns the last part of the path, which is usually the file name:

basename() بەکار دێت بۆ بەدەستهێنانی ناوی لە . وەک وەردەگرێت، دواتر دوایین بەشی دەهێنێتەوە کە بەگشتی بریتییە لە ناوی :

PHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
$path = '/var/www/html/index.php';
$filename = basename($path);
echo $filename; // Outputs: index.php

To remove the as well, give the extension as a in the second argument:

ئەگەر بتەوێت لابەیت، واتە ناوی بەبێ وەربگریت، دەتوانیت لە دووەمدا وەک دیاری بکەیت:

PHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
$path = '/var/www/html/index.php';
$filename = basename($path, '.php');
echo $filename; // Outputs: index

In uploads, basename() makes sure that a name like ../../config.php cannot climb out of your folder:

لە ، basename() دڵنیا دەبێتەوە کە ناوێکی وەک ../../config.php ناتوانێت لە دەربچێت:

PHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
echo basename("Uploads/sub/pic.png"), "<br>";
echo basename("../../config.php"), "<br>";
echo basename("holiday photo.JPG"), "<br>";
Quick checkپشکنینی خێراWhat does basename("../../config.php") return?basename("../../config.php") چی دەگەڕێنێتەوە؟

Step 2: check the fileهەنگاوی ٢: فایلەکە بپشکنە

Now we can add some restrictions. Each check below adds a message to $errors when something is wrong. After all checks, the file is moved only if $errors is still empty (see Every check must stop the upload).

ئێستا دەتوانین هەندێک سنوور زیاد بکەین. هەر پشکنینێکی خوارەوە کاتێک شتێک هەڵە بێت پەیامێک بۆ $errors زیاد دەکات. دوای هەموو پشکنینەکان، تەنها ئەو کاتە دەگوازرێتەوە کە $errors هێشتا بەتاڵ بێت (بڕوانە هەموو پشکنینێک دەبێت بارکردنەکە ڕابگرێت).

Step 2: check the fileهەنگاوی ٢: فایلەکە بپشکنە

Did the upload work?ئایا بارکردنەکە سەرکەوتوو بوو؟

Before anything else, look at the error key. Only UPLOAD_ERR_OK (0) means that a complete file is waiting in the temporary folder.

پێش هەموو شتێک، سەیری error بکە. تەنها UPLOAD_ERR_OK ⁦(0)⁩ واتای ئەوەیە کە تەواو لە کاتییەکەدا چاوەڕێ دەکات.

PHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
// Did the upload itself work?
if ($_FILES["image"]["error"] !== UPLOAD_ERR_OK) {
    $errors[] = "The upload failed (error code " . $_FILES["image"]["error"] . ").";
}

With PHP's default upload_max_filesize = 2M, our 3 MB picture did not even reach the script's checks: PHP stopped it and set the error code to 1. The complete script below shows:

بە بنەڕەتیی PHP، واتە upload_max_filesize = 2M، وێنە ٣ مێگابایتییەکەمان نەگەیشتە پشکنینەکانی : PHP ڕایگرت و کۆدی کردە 1. تەواوەکەی خوارەوە پیشان دەدات:

What the browser showsئەوەی تۆڕگەڕ پیشانی دەدات
Upload a photo
The upload failed (error code 1).
HTML sent to the browserئەو HTMLـەی دەنێردرێت بۆ تۆڕگەڕ
<h1>Upload a photo</h1>
<p style="color: red">The upload failed (error code 1).</p>

Step 2: check the fileهەنگاوی ٢: فایلەکە بپشکنە

Does the file already exist?ئایا فایلەکە پێشتر هەیە؟

First, we check whether a file with the same name already exists in the Uploads folder. If it does, an error message is added, so that the new file does not silently replace the old one:

سەرەتا دەپشکنین ئایا بە هەمان ناو پێشتر لە Uploadsدا هەیە. ئەگەر هەبێت، زیاد دەکرێت، بۆ ئەوەی نوێیەکە بە بێدەنگی جێی کۆنەکە نەگرێتەوە:

PHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
// Check if the file already exists
if (file_exists($target_file)) {
    $errors[] = "Sorry, this file already exists.";
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 2

file_exists() returns true if a file or folder with this path exists.

file_exists() ئەگەر یان بەم هەبێت true دەگەڕێنێتەوە.

In the safe version at the end of this lecture, every file gets a new random name, so two uploads can no longer have the same name; the file_exists() check stays only as a safety net.

لە وەشانە سەلامەتەکەی کۆتایی ئەم وانەیەدا، هەموو ناوێکی نوێی هەڕەمەکی وەردەگرێت، بۆیە ئیتر دوو ناتوانن هەمان ناویان هەبێت؛ پشکنینی file_exists() تەنها وەک تۆڕی سەلامەتی دەمێنێتەوە.

Step 2: check the fileهەنگاوی ٢: فایلەکە بپشکنە

Limit the file sizeقەبارەی فایل سنووردار بکە

Next, we check the size of the file. If the file is larger than 500,000 bytes (about 500 KB), an error message is added:

دواتر قەبارەی دەپشکنین. ئەگەر لە ٥٠٠،٠٠٠ (نزیکەی ٥٠٠ ) گەورەتر بێت، زیاد دەکرێت:

PHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
// Check the file size (here: at most 500000 bytes)
if ($file_size > 500000) {
    $errors[] = "Sorry, your file is too large.";
}

The course uses three different limits. Here is what they mean (1 KB = 1024 bytes, 1 MB = 1024 KB):

کۆرسەکە سێ سنووری جیاواز بەکار دەهێنێت. ئەمە واتاکەیانە (١ = ١٠٢٤ ، ١ = ١٠٢٤ ):

PHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
echo 500000 / 1024, " KB<br>";
echo 2 * 1024 * 1024, " bytes<br>";
echo 5000000 / (1024 * 1024), " MB<br>";
Limit in the codeسنوور لە کۆدەکەداWhereلە کوێIn KB / MBبە /
500000Lecture 6 and Lab 6, size checkوانەی ٦ و تاقیگەی ٦، پشکنینی قەبارەabout 488 KBنزیکەی ٤٨٨
2097152Complete scripts (lecture, lab, summary) تەواوەکان (وانە، تاقیگە، پوختە)exactly 2 MB (2 × 1024 × 1024)ڕێک ٢ ⁦(2 × 1024 × 1024)⁩
5000000A student's practice codeکۆدی ڕاهێنانی قوتابییەکabout 4.77 MBنزیکەی ٤.٧٧
Quick checkپشکنینی خێراThe check is if ($file_size > 2097152). Which file is refused?پشکنینەکە if ($file_size > 2097152)ـە. کام ڕەت دەکرێتەوە؟

Step 2: check the fileهەنگاوی ٢: فایلەکە بپشکنە

Limit the file typeجۆری فایل سنووردار بکە

Then we allow only certain file types. First we create an array of allowed extensions; after that we check whether the file's extension appears in the list:

پاشان تەنها ڕێگە بە هەندێک دەدەین. سەرەتا لە کە ڕێگەپێدراون دروست دەکەین؛ دوای ئەوە دەپشکنین ئایا لە لیستەکەدا هەیە:

PHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
// Allow only certain file extensions
$extensions = ["jpeg", "jpg", "png"];
if (in_array($file_ext, $extensions) === false) {
    $errors[] = "Extension not allowed, please choose a JPEG or PNG file.";
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 3

in_array() returns true if the value is in the array. === false means "not in the list".

in_array() ئەگەر لە بێت true دەگەڕێنێتەوە. === false واتە «لە لیستەکەدا نییە».

The triple equals sign === checks that two values are equal and of the same type:

نیشانەی سێ یەکسانی === دەپشکنێت کە دوو یەکسانن و هەمان جۆریان هەیە:

PHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
var_dump(0 == false);   // same value after conversion
var_dump(0 === false);  // different types: integer and boolean

Step 2: check the fileهەنگاوی ٢: فایلەکە بپشکنە

The extension is not proof: check the real typeپاشگری فایل بەڵگە نییە: جۆری ڕاستەقینە بپشکنە

A file's name and its type are chosen by the visitor. Anyone can rename shell.php to cat.jpg, and the browser will happily report image/jpeg. To know what a file really is, look at its content. PHP's fileinfo functions read the first bytes of the file and give its real :

ناو و typeی لەلایەن سەردانکەرەوە هەڵدەبژێردرێن. هەر کەسێک دەتوانێت ناوی shell.php بگۆڕێت بۆ cat.jpg و بە خۆشحاڵییەوە image/jpeg ڕادەگەیەنێت. بۆ ئەوەی بزانیت بە ڕاستی چییە، سەیری ناوەڕۆکەکەی بکە. fileinfo لە PHPـدا یەکەم دەخوێننەوە و جۆری ڕاستەقینەی () دەدەن:

real-type.phpPHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
$finfo = finfo_open(FILEINFO_MIME_TYPE);
foreach (["cat.png", "erbil.jpg", "fake.jpg", "notes.txt"] as $file) {
    echo $file . " is really: " . finfo_file($finfo, $file) . "<br>\n";
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 2

Open the fileinfo database once.

fileinfo یەکجار بکەرەوە.

Lineدێڕی 4

finfo_file() returns the real type of the content.

finfo_file() جۆری ڕاستەقینەی ناوەڕۆکەکە دەگەڕێنێتەوە.

The real-type check in the upload scriptپشکنینی جۆری ڕاستەقینە لە دەسنووسی بارکردنداPHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
// Check the real type of the file's content
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$realType = finfo_file($finfo, $file_tmp);
if (!in_array($realType, ["image/jpeg", "image/png"], true)) {
    $errors[] = "This file is not a real JPEG or PNG picture.";
}
Quick checkپشکنینی خێراSomeone renames shell.php to cat.jpg and uploads it. Which check stops it?کەسێک ناوی shell.php دەگۆڕێت بۆ cat.jpg و باری دەکات. کام پشکنین ڕایدەگرێت؟

Every check must stop the uploadهەموو پشکنینێک دەبێت بارکردنەکە ڕابگرێت

The course's complete script puts the steps together, and ends with move_uploaded_file(temp, destination), which moves the uploaded temporary file to the target folder. It prints "Success" if $errors is empty, and the collected errors otherwise. But look closely: each check only echoes its message. Nothing is ever added to $errors, so empty($errors) is always true. Here is the slide's script, with only the missing } added, tested with a 9 MB file called virus.exe:

تەواوەکەی کۆرسەکە هەنگاوەکان پێکەوە دادەنێت و بە move_uploaded_file(temp, destination) کۆتایی دێت، کە کاتییە بارکراوەکە دەگوازێتەوە بۆ ئامانج. ئەگەر $errors بەتاڵ بێت «Success» چاپ دەکات، دەنا هەڵە کۆکراوەکان. بەڵام بە وردی سەیر بکە: هەر پشکنینێک تەنها پەیامەکەی echo دەکات. هەرگیز هیچ شتێک بۆ $errors زیاد ناکرێت، بۆیە empty($errors) هەمیشە ڕاستە. ئەمە ، تەنها }ی لەبیرکراوی بۆ زیاد کراوە و بە ٩ بە ناوی virus.exe تاقیکراوەتەوە:

The slide's complete script, only the missing } added (do not use)دەسنووسە تەواوەکەی سلایدەکە، تەنها }ی لەبیرکراوی بۆ زیاد کراوە (بەکاری مەهێنە)upload.phpPHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php   if(isset($_POST['submit'])){
$target_dir="Uploads/";
$errors="";
$file_name = $_FILES['image']['name'];
$file_size =$_FILES['image']['size'];
$file_tmp =$_FILES['image']['tmp_name'];
$file_type=$_FILES['image']['type'];
$file_ext=strtolower(end(explode('.',$_FILES['image']['name'])));
$target=$target_dir.basename($file_name);
$expensions= array("jpeg","jpg","png");

if (file_exists($target)) {
   echo "this file already exist<br>";
}
if (in_array($file_ext, $expensions) === false)
{
   echo "extension not allowed, please choose a JPEG or PNG file.<br>";
}
if ($file_size > 2097152) {
   echo 'File size must be excately 2 MB<br>';
}
if (empty($errors) == true) {
   move_uploaded_file($file_tmp, $target_dir . $file_name);
   echo "Success";
} else {
   print($errors);
}
}
?>
Quick checkپشکنینی خێراIn the slide's script every check only echoes a message. What happens to a file that fails a check?لە هەموو پشکنینێک تەنها پەیامێک echo دەکات. چی بەسەر دێت کە لە پشکنینێکدا دەرنەچێت؟

There are two correct ways to make every check block the upload.

دوو ڕێگای دروست هەیە بۆ ئەوەی هەموو پشکنینێک ڕابگرێت.

Every check must stop the uploadهەموو پشکنینێک دەبێت بارکردنەکە ڕابگرێت

Way 1: collect the errors, move only when there are noneڕێگای ١: هەڵەکان کۆ بکەرەوە، تەنها کاتێک هیچ نییە بیگوازەرەوە

Every check adds its message to $errors (the summary does this correctly with $errors .= "...", and so does the lecture's extension check). At the end, the file is moved only if $errors is empty. The visitor sees all problems at once.

هەموو پشکنینێک پەیامەکەی بۆ $errors زیاد دەکات (پوختەکە ئەمە بە دروستی بە $errors .= "..." دەکات، هەروەها پشکنینی وانەکەش). لە کۆتاییدا تەنها ئەو کاتە دەگوازرێتەوە کە $errors بەتاڵ بێت. سەردانکەر هەموو کێشەکان پێکەوە دەبینێت.

The end of the scriptکۆتایی دەسنووسەکەPHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
// Only when there are no errors: move the file and check the result
if (empty($errors)) {
    if (move_uploaded_file($file_tmp, $target_file)) {
        echo "Success! The file was uploaded.";
    } else {
        echo "Sorry, the file could not be saved.";
    }
} else {
    foreach ($errors as $error) {
        echo $error . "<br>";
    }
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 3

move_uploaded_file() takes exactly two arguments: the temporary file and the destination path. It returns true or false.

move_uploaded_file() ڕێک دوو وەردەگرێت: و شوێنی مەبەست. true یان false دەگەڕێنێتەوە.

Lineدێڕی 9-11

Show every collected message.

هەموو پەیامە کۆکراوەکان پیشان بدە.

Every check must stop the uploadهەموو پشکنینێک دەبێت بارکردنەکە ڕابگرێت

Way 2: one if/elseif chain (the lab's complete version)ڕێگای ٢: یەک زنجیرەی ⁦if/elseif⁩ (وەشانە تەواوەکەی تاقیگە)

Lab 6's final page uses one if/elseif chain: the first failing check prints its message, and the else at the end (which moves the file) runs only if no check failed. Here it is with the small fixes (pathinfo, basename(), clear messages, and a check of the move's result):

لاپەڕە کۆتاییەکەی تاقیگەی ٦ یەک زنجیرەی if/elseif بەکار دەهێنێت: یەکەم پشکنینی شکستخواردوو پەیامەکەی چاپ دەکات و لە کۆتاییدا (کە دەگوازێتەوە) تەنها ئەو کاتە جێبەجێ دەکرێت کە هیچ پشکنینێک شکستی نەهێنابێت. ئەمە بە چاکسازییە بچووکەکانەوەیە (pathinfo، basename()، پەیامی ڕوون و پشکنینی ئەنجامی گواستنەوەکە):

index.php (lab version, corrected)PHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
if (isset($_POST['submit'])) {
    $target_dir = "Uploads/";
    $file_name = basename($_FILES['image']['name']);
    $file_size = $_FILES['image']['size'];
    $file_tmp = $_FILES['image']['tmp_name'];
    $file_ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
    $target = $target_dir . $file_name;
    $extensions = array("jpeg", "jpg", "png");

    if (empty($file_name)) {
        echo "Please select a file.";
    } elseif (file_exists($target)) {
        echo "Sorry, this file already exists.";
    } elseif (in_array($file_ext, $extensions) === false) {
        echo "Extension not allowed, please choose a JPEG or PNG file.";
    } elseif ($file_size > 2097152) {
        echo "The file must not be bigger than 2 MB.";
    } elseif (move_uploaded_file($file_tmp, $target)) {
        echo "Success";
    } else {
        echo "Sorry, the file could not be saved.";
    }
}
?>
<!DOCTYPE html>
<html>
<body>
<form action="index.php" method="POST" enctype="multipart/form-data">
    <input type="file" name="image">
    <input type="submit" name="submit">
</form>
</body>
</html>
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 24-31

The form from the lab sheet. It posts to index.php, so the PHP and the form must be saved together in index.php. The lab's page stops after </form>; close </body> and </html> too.

پەڕەی تاقیگەکە. بۆ index.php دەنێرێت، بۆیە PHPـەکە و دەبێت پێکەوە لە index.phpدا خەزن بکرێن. لاپەڕەکەی تاقیگە دوای </form> دەوەستێت؛ </body> و </html>یش دابخە.

Three uploads, one after the other (tested). Only cat.png was saved.سێ ، یەک لە دوای یەک (تاقیکراوەتەوە). تەنها ⁦cat.png⁩ خەزن کرا.
Uploaded file بارکراوOutput
virus.exe (9 MB)Extension not allowed, please choose a JPEG or PNG file.
cat.pngSuccess
cat.png (again)Sorry, this file already exists.

Way 1 tells the visitor about every problem at once; way 2 tells them about the first problem only. Both are correct, because in both the move happens only when every check has passed.

ڕێگای ١ دەربارەی هەموو کێشەکان پێکەوە بە سەردانکەر دەڵێت؛ ڕێگای ٢ تەنها دەربارەی یەکەم کێشە. هەردووکیان دروستن، چونکە لە هەردووکیاندا گواستنەوەکە تەنها ئەو کاتە ڕوودەدات کە هەموو پشکنینێک تێپەڕیبێت.

Quick checkپشکنینی خێراWhat does move_uploaded_file($tmp, "Uploads/", $name) do in PHP 8?move_uploaded_file($tmp, "Uploads/", $name) لە ⁦PHP 8⁩دا چی دەکات؟

The complete, safe upload pageلاپەڕەی بارکردنی تەواو و سەلامەت

Here is the whole upload page in one file, index.php, with the form at the bottom and the PHP at the top. It keeps the course's checks (submit, existing file, size, extension) and adds the protections that a real site needs: it checks the error key and the real type, never uses the visitor's file name on the disk, and checks the result of move_uploaded_file().

ئەمە هەموو لاپەڕەی لە یەک ، index.php، لە خوارەوە و PHPـەکە لە سەرەوە. پشکنینەکانی کۆرسەکە دەهێڵێتەوە (ناردن، هەبوو، قەبارە، ) و ئەو پاراستنانەی زیاد دەکات کە ڕاستەقینە پێویستی پێیانە: error و جۆری ڕاستەقینە دەپشکنێت، هەرگیز ناوی سەردانکەر لەسەر دیسک بەکار ناهێنێت و ئەنجامی move_uploaded_file() دەپشکنێت.

index.phpPHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
// index.php - upload a photo (JPEG or PNG, at most 2 MB)
$uploadDir  = __DIR__ . "/Uploads/";       // the folder must exist
$maxSize    = 2097152;                     // 2 MB = 2 * 1024 * 1024 bytes
$extensions = ["jpeg", "jpg", "png"];      // allowed file extensions
$mimeTypes  = ["image/jpeg", "image/png"]; // allowed real file types
$errors     = [];                          // collects error messages
$message    = "";

if (isset($_POST["submit"])) {
    $file = $_FILES["image"] ?? null;

    if ($file === null || $file["error"] === UPLOAD_ERR_NO_FILE) {
        $errors[] = "Please select a file.";
    } elseif ($file["error"] !== UPLOAD_ERR_OK) {
        $errors[] = "The upload failed (error code " . $file["error"] . ").";
    } else {
        $originalName = basename($file["name"]);
        $ext = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));

        if (!in_array($ext, $extensions, true)) {
            $errors[] = "Extension not allowed. Please choose a JPEG or PNG file.";
        }
        if ($file["size"] > $maxSize) {
            $errors[] = "The file is too large. It must not be bigger than 2 MB.";
        }
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $realType = finfo_file($finfo, $file["tmp_name"]);
        if (!in_array($realType, $mimeTypes, true)) {
            $errors[] = "This file is not a real JPEG or PNG picture.";
        }

        if (empty($errors)) {
            // a new, random name: the visitor cannot choose it
            $newName = bin2hex(random_bytes(16)) . "." . $ext;
            $target  = $uploadDir . $newName;

            if (file_exists($target)) {
                $errors[] = "Sorry, this file already exists.";
            } elseif (move_uploaded_file($file["tmp_name"], $target)) {
                $message = "Success! " . htmlspecialchars($originalName) . " was uploaded.";
            } else {
                $errors[] = "Sorry, the file could not be saved.";
            }
        }
    }
}
?>
<!DOCTYPE html>
<html>
<body>
<h1>Upload a photo</h1>
<?php
foreach ($errors as $error) {
    echo "<p style=\"color: red\">$error</p>\n";
}
if ($message !== "") {
    echo "<p style=\"color: green\">$message</p>\n";
}
?>
<form action="index.php" method="post" enctype="multipart/form-data">
  Select image to upload:
  <input type="file" name="image" accept=".jpg,.jpeg,.png">
  <input type="submit" name="submit" value="Upload Image">
</form>
</body>
</html>
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 3-8

Settings in one place: the folder, the size limit, the allowed extensions and real types, and the list of errors.

لە یەک شوێندا: ، سنووری قەبارە، و جۆرە ڕاستەقینە ڕێگەپێدراوەکان و لیستی .

Lineدێڕی 11

?? gives null when there is no image file at all (for example a form without enctype).

?? کاتێک هیچ image نەبێت null دەدات (بۆ نموونە بەبێ enctype).

Lineدێڕی 13-16

No file chosen, or the upload failed: stop here.

هیچ هەڵنەبژێردراوە، یان شکستی هێنا: لێرە بوەستە.

Lineدێڕی 18-19

Never trust the name: keep only the last part, and take the extension with pathinfo().

هەرگیز متمانە بە ناوەکە مەکە: تەنها بەشی کۆتایی بهێڵەوە و بە pathinfo() وەربگرە.

Lineدێڕی 21-31

Three checks; each one adds a message.

سێ پشکنین؛ هەر یەکێکیان پەیامێک زیاد دەکات.

Lineدێڕی 27-28

The real type, read from the file's content.

جۆری ڕاستەقینە، کە لە ناوەڕۆکی خوێندراوەتەوە.

Lineدێڕی 33

Move only when there is no error.

تەنها کاتێک هیچ نییە بیگوازەرەوە.

Lineدێڕی 35

A new random name such as 9f86d081...c3.png. The visitor cannot choose it, and two uploads never collide.

ناوێکی نوێی هەڕەمەکی وەک 9f86d081...c3.png. سەردانکەر ناتوانێت هەڵیبژێرێت و دوو هەرگیز تێکهەڵناچن.

Lineدێڕی 38-44

The course's exists check stays as a safety net; then move, and check that it worked.

پشکنینی هەبوونی کۆرسەکە وەک تۆڕی سەلامەتی دەمێنێتەوە؛ پاشان بیگوازەرەوە و بپشکنە کە کاری کرد.

Lineدێڕی 41

The original name is shown with htmlspecialchars(), because a file name can contain HTML.

ناوە ڕەسەنەکە بە htmlspecialchars() پیشان دەدرێت، چونکە ناوی دەتوانێت HTMLـی تێدابێت.

Lineدێڕی 61

The form: post and multipart/form-data; accept only helps the visitor choose.

: post و multipart/form-data؛ accept تەنها یارمەتیی سەردانکەر دەدات بۆ هەڵبژاردن.

The complete, safe upload pageلاپەڕەی بارکردنی تەواو و سەلامەت

Tested with six uploadsتاقیکراوەتەوە بە شەش بارکردن

We sent six requests to the complete index.php. The messages below are the part of each page that changed:

شەش بۆ index.phpـە تەواوەکە نارد. پەیامەکانی خوارەوە ئەو بەشەی هەر لاپەڕەیەکن کە گۆڕا:

First visit (no upload yet)یەکەم سەردان (هێشتا هیچ بارکردنێک نییە)
Upload a photo
Select image to upload: [Choose File] No file chosen [Upload Image]
HTML sent to the browserئەو HTMLـەی دەنێردرێت بۆ تۆڕگەڕ
<!DOCTYPE html>
<html>
<body>
<h1>Upload a photo</h1>
<form action="index.php" method="post" enctype="multipart/form-data">
  Select image to upload:
  <input type="file" name="image" accept=".jpg,.jpeg,.png">
  <input type="submit" name="submit" value="Upload Image">
</form>
</body>
</html>
Upload: cat.png, a real PNG picture (123 bytes)بارکردن: ⁦cat.png⁩، وێنەیەکی ڕاستەقینەی PNG (١٢٣ بایت)
Upload a photo
Success! cat.png was uploaded.
HTML sent to the browserئەو HTMLـەی دەنێردرێت بۆ تۆڕگەڕ
<h1>Upload a photo</h1>
<p style="color: green">Success! cat.png was uploaded.</p>
Upload: fake.jpg, PHP code renamed to .jpgبارکردن: ⁦fake.jpg⁩، کۆدی PHP کە ناوی گۆڕدراوە بۆ ⁦.jpg⁩
Upload a photo
This file is not a real JPEG or PNG picture.
HTML sent to the browserئەو HTMLـەی دەنێردرێت بۆ تۆڕگەڕ
<h1>Upload a photo</h1>
<p style="color: red">This file is not a real JPEG or PNG picture.</p>
Upload: virus.exe, 9 MBبارکردن: ⁦virus.exe⁩، ٩ مێگابایت
Upload a photo
Extension not allowed. Please choose a JPEG or PNG file.
The file is too large. It must not be bigger than 2 MB.
This file is not a real JPEG or PNG picture.
HTML sent to the browserئەو HTMLـەی دەنێردرێت بۆ تۆڕگەڕ
<h1>Upload a photo</h1>
<p style="color: red">Extension not allowed. Please choose a JPEG or PNG file.</p>
<p style="color: red">The file is too large. It must not be bigger than 2 MB.</p>
<p style="color: red">This file is not a real JPEG or PNG picture.</p>
Upload: big.png, a real PNG of 3 MBبارکردن: ⁦big.png⁩، PNGـێکی ڕاستەقینەی ٣ مێگابایتی
Upload a photo
The file is too large. It must not be bigger than 2 MB.
HTML sent to the browserئەو HTMLـەی دەنێردرێت بۆ تۆڕگەڕ
<h1>Upload a photo</h1>
<p style="color: red">The file is too large. It must not be bigger than 2 MB.</p>
Submit without choosing a fileناردن بەبێ هەڵبژاردنی فایل
Upload a photo
Please select a file.
HTML sent to the browserئەو HTMLـەی دەنێردرێت بۆ تۆڕگەڕ
<h1>Upload a photo</h1>
<p style="color: red">Please select a file.</p>

These tests ran with upload_max_filesize and post_max_size set to 40M. Afterwards the Uploads folder held exactly one new file, 6fc3301d....png: only the real picture was kept, under a random name.

ئەم تاقیکردنەوانە بە upload_max_filesize و post_max_size ـی ⁦40M⁩ جێبەجێ کران. دواتر Uploads ڕێک یەک نوێی تێدابوو، 6fc3301d....png: تەنها وێنە ڕاستەقینەکە هەڵگیرا، بە ناوێکی هەڕەمەکی.

The complete, safe upload pageلاپەڕەی بارکردنی تەواو و سەلامەت

Keep uploaded files from runningڕێگە مەدە فایلەکان بارکراوەکان جێبەجێ بکرێن

The Uploads folder is inside your website, so anyone can open a file in it with its address. Even with all the checks, store uploads so that they can never run as a program. There are two ways:

Uploads لەناو ، بۆیە هەر کەسێک دەتوانێت ناوی بە ناونیشانەکەی بکاتەوە. تەنانەت لەگەڵ هەموو پشکنینەکانیش، بارکراوەکان بە شێوەیەک هەڵبگرە کە هەرگیز نەتوانن وەک جێبەجێ بکرێن. دوو ڕێگا هەیە:

  1. Best: keep them outside the web root. The web root is the public folder that the server shows to everyone ( in XAMPP). A folder next to it, such as C:\xampp\private_uploads, cannot be opened from a browser at all; a small PHP page sends the pictures when needed (see the next section).
  2. If the folder must stay inside the website, block scripts in it. On Apache (XAMPP) put this .htaccess file inside Uploads/:
  1. باشترین: لە دەرەوەی ڕەگی وێب هەڵیانبگرە. ڕەگی وێب ئەو گشتییەیە کە بە هەمووانی پیشان دەدات ( لە XAMPPـدا). لە تەنیشتیەوە، وەک C:\xampp\private_uploads، هەرگیز لە ناکرێتەوە؛ لاپەڕەیەکی بچووکی PHP کاتێک پێویست بوو وێنەکان دەنێرێت (بەشی داهاتوو ببینە).
  2. ئەگەر دەبێت لەناو بمێنێتەوە، تێدا ڕابگرە. لەسەر ⁦Apache (XAMPP)⁩ ئەم .htaccessـە بخە ناو Uploads/ەوە:
Uploads/.htaccessAPACHE
# Uploads/.htaccess - this folder only stores pictures
# 1. Never run or send any PHP file from this folder
<FilesMatch "\.(php|phtml|phar)$">
    Require all denied
</FilesMatch>
# 2. Do not show a list of the files in this folder
Options -Indexes
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 3-5

Refuse every request for a PHP file in this folder, so an uploaded script can never run.

هەموو بۆ PHP لەم ڕەت بکەرەوە، بۆ ئەوەی بارکراو هەرگیز جێبەجێ نەبێت.

Lineدێڕی 7

Do not show a list of the folder's files.

لیستی پیشان مەدە.

Quick checkپشکنینی خێراWhy do we put an .htaccess file that denies .php files into the Uploads folder?بۆچی .htaccess کە ڕێگە بە .php نادات دەخەینە ناو Uploadsەوە؟

Showing files that are stored outside the web rootپیشاندانی ئەو فایلانەی لە دەرەوەی ڕەگی وێب هەڵگیراون

If the pictures are in private_uploads, next to the web root, the browser cannot open them by address. A small script reads the file and sends it, with the right Content-Type . It uses basename() so that the visitor can only ask for a file inside that folder:

ئەگەر وێنەکان لە private_uploadsدا بن، لە تەنیشت ڕەگی وێبەوە، ناتوانێت بە ناونیشان بیانکاتەوە. بچووک دەخوێنێتەوە و دەینێرێت، لەگەڵ Content-Typeی دروست. basename() بەکار دەهێنێت بۆ ئەوەی سەردانکەر تەنها بتوانێت داوای بکات کە لەناو ئەو :

photo.phpPHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
// photo.php?name=... sends one stored photo to the browser
$dir  = dirname(__DIR__) . "/private_uploads/";  // outside the web root
$name = basename($_GET["name"] ?? "");           // basename() blocks "../" tricks
$path = $dir . $name;

if ($name === "" || !is_file($path)) {
    http_response_code(404);
    exit("Photo not found.");
}

$finfo = finfo_open(FILEINFO_MIME_TYPE);
header("Content-Type: " . finfo_file($finfo, $path));
readfile($path);
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 3

dirname(__DIR__) is the folder above the web root.

dirname(__DIR__) ئەو کە لە سەرووی ڕەگی وێبەوەیە.

Lineدێڕی 8-9

Unknown name: answer 404 (Not Found) and stop.

ناوی نەناسراو: بە ⁦404 (Not Found)⁩ وەڵام بدەرەوە و بوەستە.

Lineدێڕی 12-14

Tell the browser the real type, then send the file's bytes.

جۆرە ڕاستەقینەکە بە بڵێ، پاشان بنێرە.

Two tested requests: the picture is sent; the "../" trick gets nothingدوو تاقیکراو: وێنەکە دەنێردرێت؛ فێڵی «../» هیچ وەرناگرێت
RequestStatusدۆخContent-Type
photo.php?name=dac0e95b...54.png200image/png
photo.php?name=../html/photo.php404 (Photo not found.)text/html; charset=UTF-8

In the HTML page you then write <img src="photo.php?name=...">, using the stored name from your database.

پاشان لە لاپەڕەی HTMLـدا دەنووسیت <img src="photo.php?name=...">، بە بەکارهێنانی ئەو ناوەی لە هەڵگیراوە.

Storing the file in the database (BLOB)هەڵگرتنی فایل لە بنکەدراوەدا ⁦(BLOB)⁩

The alternate method stores the file's bytes inside a . The course gives four steps:

ڕێگا جێگرەوەکە لەناو هەڵدەگرێت. کۆرسەکە چوار هەنگاو دەدات:

The BLOB method in four stepsڕێگای BLOB لە چوار هەنگاودا
  1. Step 1: create a table with a LONGBLOB columnهەنگاوی ١: خشتەیەک بە ستوونێکی LONGBLOB دروست بکە

    A LONGBLOB column holds up to 4 GB of binary data. Store the name and the real type next to it, so that you can send the file back later.

    LONGBLOB تا ٤ دووانەیی هەڵدەگرێت. ناو و جۆرە ڕاستەقینەکەش لە تەنیشتیەوە هەڵبگرە، بۆ ئەوەی دواتر بتوانیت بنێریتەوە.

    SQLRuns in the databaseلە ناو بنکەدراوە کار دەکات
    CREATE TABLE uploads (
        id   INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(255) NOT NULL,
        type VARCHAR(100) NOT NULL,
        data LONGBLOB NOT NULL
    );
  2. Step 2: prepare the fileهەنگاوی ٢: فایلەکە ئامادە بکە

    Run the same checks as before. Then file_get_contents() reads the entire file into a string. (filesize() returns the file size, if you need it.)

    هەمان پشکنینەکانی پێشوو جێبەجێ بکە. پاشان file_get_contents() هەموو دەخوێنێتەوە بۆ ناو . (filesize() قەبارەی دەگەڕێنێتەوە، ئەگەر پێویستت پێی بێت.)

  3. Step 3: create and run the query, as a prepared statementهەنگاوی ٣: پرسەکە دروست بکە و جێبەجێی بکە، وەک ڕستەی ئامادەکراو

    Send the data as a parameter of a , never inside the SQL text.

    وەک بنێرە، هەرگیز لەناو دەقی SQLـدا نا.

  4. Step 4: tell the userهەنگاوی ٤: بە بەکارهێنەر بڵێ

    Check all the previous factors and display an appropriate message to the user.

    هەموو هۆکارەکانی پێشوو بپشکنە و پەیامێکی گونجاو بە پیشان بدە.

save-to-db.php (MySQL)PHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
require 'dbcon.php';                 // gives $con, the MySQL connection

// ... first run the same checks as the folder method:
//     error code, size, extension and real type ($realType) ...

if (empty($errors)) {
    // Step 2: prepare the file
    $name = basename($_FILES["image"]["name"]);
    $data = file_get_contents($_FILES["image"]["tmp_name"]);   // the whole file as a string

    // Step 3: create and run the query - as a prepared statement
    $stmt = mysqli_prepare($con, "INSERT INTO uploads (name, type, data) VALUES (?, ?, ?)");
    mysqli_stmt_bind_param($stmt, "sss", $name, $realType, $data);
    mysqli_stmt_execute($stmt);

    // Step 4: tell the user what happened
    echo "The picture was saved in the database.";
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 2

dbcon.php creates the connection $con (see Including files).

dbcon.php پەیوەندیی $con دروست دەکات (بڕوانە هاوردەکردنی فایل).

Lineدێڕی 10

Reads the entire file into a string.

هەموو دەخوێنێتەوە بۆ ناو .

Lineدێڕی 13

The SQL has a ? (a placeholder, also called a parameter marker) in place of each value.

لە SQLـەکەدا لە جیاتی هەر ، ?ێک وەک دانراوە.

Lineدێڕی 14

Bind the three values as strings ("sss"); binary data is safe here because it never becomes part of the SQL text.

سێ وەک ببەستەوە ("sss")؛ دووانەیی لێرەدا سەلامەتە چونکە هەرگیز نابێتە بەشێک لە دەقی SQL.

Storing the file in the database (BLOB)هەڵگرتنی فایل لە بنکەدراوەدا ⁦(BLOB)⁩

What was wrong in the slide's BLOB codeچی لە کۆدی BLOB ـی سلایدەکەدا هەڵە بوو

Quick checkپشکنینی خێراWhy is the slide's addslashes() + string-built INSERT not safe enough?بۆچی addslashes() لەگەڵ INSERTـێک کە بە دروست کراوە بەس نییە؟

Storing the file in the database (BLOB)هەڵگرتنی فایل لە بنکەدراوەدا ⁦(BLOB)⁩

Trying the BLOB method with SQLiteتاقیکردنەوەی ڕێگای BLOB بە SQLite

The MySQL code above needs a MySQL server, so its output is not shown. To prove that the method works, here is the same idea with , which runs without a server (you will meet PDO and SQLite later in the course):

کۆدە MySQLـییەکەی سەرەوە پێویستی بە MySQL هەیە، بۆیە پیشان نادرێت. بۆ سەلماندنی ئەوەی ڕێگاکە کار دەکات، ئەمە هەمان بیرۆکەیە بە ، کە بەبێ کار دەکات (دواتر لە کۆرسەکەدا PDO و SQLite دەبینیت):

blob-sqlite.phpPHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
// The BLOB method with SQLite (PDO), so you can try it without MySQL
$db = new PDO("sqlite:" . __DIR__ . "/photos.sqlite");

// Step 1: a table with a BLOB column (created only the first time)
$db->exec("CREATE TABLE IF NOT EXISTS uploads (
    id   INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    type TEXT NOT NULL,
    data BLOB NOT NULL
)");

if (isset($_POST["submit"]) && $_FILES["image"]["error"] === UPLOAD_ERR_OK) {
    // Step 2: prepare the file
    $tmp  = $_FILES["image"]["tmp_name"];
    $name = basename($_FILES["image"]["name"]);
    $type = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $tmp);
    $data = file_get_contents($tmp);          // the whole file as one string

    // Step 4 (the checks) comes before saving
    if (!in_array($type, ["image/jpeg", "image/png"], true) || strlen($data) > 2097152) {
        exit("Only JPEG or PNG pictures up to 2 MB, please.");
    }

    // Step 3: a prepared statement - the data never becomes part of the SQL text
    $stmt = $db->prepare("INSERT INTO uploads (name, type, data) VALUES (?, ?, ?)");
    $stmt->bindValue(1, $name);
    $stmt->bindValue(2, $type);
    $stmt->bindValue(3, $data, PDO::PARAM_LOB);
    $stmt->execute();

    echo "Saved " . htmlspecialchars($name) . " (" . strlen($data) . " bytes) in the database.<br>\n";
}

foreach ($db->query("SELECT id, name, type, length(data) AS bytes FROM uploads") as $row) {
    echo $row["id"] . ": " . htmlspecialchars($row["name"]) . ", " . $row["type"] . ", " . $row["bytes"] . " bytes<br>\n";
}
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 26-29

A prepared statement; PDO::PARAM_LOB marks the value as binary data.

؛ PDO::PARAM_LOB وەک دووانەیی نیشانە دەکات.

1. Upload cat.png١. بارکردنی ⁦cat.png⁩
Saved cat.png (123 bytes) in the database.
1: cat.png, image/png, 123 bytes
HTML sent to the browserئەو HTMLـەی دەنێردرێت بۆ تۆڕگەڕ
Saved cat.png (123 bytes) in the database.<br>
1: cat.png, image/png, 123 bytes<br>
2. Upload fake.jpg (PHP code)٢. بارکردنی ⁦fake.jpg⁩ (کۆدی PHP)
Only JPEG or PNG pictures up to 2 MB, please.
HTML sent to the browserئەو HTMLـەی دەنێردرێت بۆ تۆڕگەڕ
Only JPEG or PNG pictures up to 2 MB, please.
3. Upload erbil.jpg٣. بارکردنی ⁦erbil.jpg⁩
Saved erbil.jpg (653 bytes) in the database.
1: cat.png, image/png, 123 bytes
2: erbil.jpg, image/jpeg, 653 bytes
HTML sent to the browserئەو HTMLـەی دەنێردرێت بۆ تۆڕگەڕ
Saved erbil.jpg (653 bytes) in the database.<br>
1: cat.png, image/png, 123 bytes<br>
2: erbil.jpg, image/jpeg, 653 bytes<br>

Storing the file in the database (BLOB)هەڵگرتنی فایل لە بنکەدراوەدا ⁦(BLOB)⁩

Showing a picture from the databaseپیشاندانی وێنەیەک لە بنکەدراوەوە

To show a stored picture, select it with a prepared statement and send it with its type:

بۆ پیشاندانی وێنەیەکی هەڵگیراو، بە هەڵیبژێرە و لەگەڵ جۆرەکەی بینێرە:

show.php (MySQL)PHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
// show.php?id=5 - send one picture from the database to the browser
require 'dbcon.php';

$id = (int) ($_GET["id"] ?? 0);
$stmt = mysqli_prepare($con, "SELECT type, data FROM uploads WHERE id = ?");
mysqli_stmt_bind_param($stmt, "i", $id);
mysqli_stmt_execute($stmt);
$row = mysqli_fetch_assoc(mysqli_stmt_get_result($stmt));

if (!$row) {
    http_response_code(404);
    exit("Picture not found.");
}
header("Content-Type: " . $row["type"]);
echo $row["data"];

Common mistakesهەڵە باوەکان

  • No enctype="multipart/form-data" (or method="get"). PHP receives only the file name as text; $_FILES is empty. Our test without enctype: $_POST held image => "cat.png", and $_FILES was an empty array.
  • The input's name and the key in $_FILES differ (image, fileToUpload, fileInput, photo...). Use one name everywhere.
  • The target folder does not exist, or its name has the wrong case (Uploads vs uploads). move_uploaded_file() then fails with two warnings; see below.
  • Checks that only echo. The file is saved anyway. Collect errors or use an elseif chain.
  • move_uploaded_file() with three arguments, or with the misspelled key tpm_name.
  • end(explode(...)) gives a notice; use pathinfo($name, PATHINFO_EXTENSION).
  • Trusting type or the extension instead of checking the content with finfo.
  • Keeping the visitor's file name: files overwrite each other, and strange names cause trouble. Generate a new name.
  • A request bigger than post_max_size: PHP empties $_POST and $_FILES, so isset($_POST["submit"]) is false and the page just shows the form again, with a startup warning. Our test with a 9 MB file and post_max_size = 8M:
  • هیچ enctype="multipart/form-data"ێک نییە (یان method="get"). PHP تەنها ناوی وەک دەق وەردەگرێت؛ $_FILES بەتاڵە. تاقیکردنەوەکەمان بەبێ enctype: $_POST image => "cat.png"ی تێدابوو و $_FILES بەتاڵ بوو.
  • nameی و ناو $_FILES جیاوازن (image، fileToUpload، fileInput، photo...). یەک ناو لە هەموو شوێنێک بەکاربهێنە.
  • ئامانج بوونی نییە، یان ناوەکەی پیتی گەورە و بچووکی هەڵەیە (Uploads بەرامبەر uploads). ئەوکاتە move_uploaded_file() بە دوو شکست دەهێنێت؛ لە خوارەوە ببینە.
  • پشکنین کە تەنها echo دەکەن. هەر خەزن دەکرێت. کۆ بکەرەوە یان زنجیرەی elseif بەکاربهێنە.
  • move_uploaded_file() بە سێ ، یان بە بە هەڵە نووسراوی tpm_name.
  • end(explode(...)) ئاگاداری دەدات؛ pathinfo($name, PATHINFO_EXTENSION) بەکاربهێنە.
  • متمانەکردن بە type یان لە جیاتی پشکنینی ناوەڕۆک بە finfo.
  • هێشتنەوەی ناوی سەردانکەر: جێی یەکتر دەگرنەوە و ناوی سەیر کێشە دروست دەکەن. ناوێکی نوێ دروست بکە.
  • گەورەتر لە post_max_size: PHP $_POST و $_FILES بەتاڵ دەکات، بۆیە isset($_POST["submit"]) هەڵەیە و لاپەڕەکە تەنها دووبارە پیشان دەداتەوە، لەگەڵ ئاگادارییەکی دەستپێکردن. تاقیکردنەوەکەمان بە ٩ و post_max_size = 8M:
A 9 MB upload when post_max_size is 8Mبارکردنێکی ٩ مێگابایتی کاتێک ⁦post_max_size⁩ بریتییە لە ⁦8M⁩
Warning: PHP Request Startup: POST Content-Length of 9437468 bytes exceeds the limit of 8388608 bytes in Unknown on line 0
Upload a photo
HTML sent to the browserئەو HTMLـەی دەنێردرێت بۆ تۆڕگەڕ
<br />
<b>Warning</b>:  PHP Request Startup: POST Content-Length of 9437468 bytes exceeds the limit of 8388608 bytes in <b>Unknown</b> on line <b>0</b><br />
<h1>Upload a photo</h1>
Moving into a folder that does not existگواستنەوە بۆ فۆڵدەرێک کە بوونی نییەno-folder.phpPHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
if (isset($_POST["submit"])) {
    $target = "Uploads/" . basename($_FILES["image"]["name"]);   // the folder does not exist
    if (move_uploaded_file($_FILES["image"]["tmp_name"], $target)) {
        echo "Success";
    } else {
        echo "Sorry, the file could not be saved.";
    }
}
What PHP receives from a form without enctypePHP چی وەردەگرێت لە فۆرمێک بەبێ enctypeno-enctype.phpPHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
var_dump($_POST);
var_dump($_FILES);

Lab and exercisesتاقیگە و ڕاهێنانەکان

ExerciseڕاهێنانLab 6, task 2: the file_handling projectتاقیگەی ٦، ئەرکی ٢: پرۆژەی ⁦file_handling⁩

Open a new PHP project in NetBeans and name it file_handling. (1) Create a new folder in the project called Uploads. (2) Write the HTML form for uploading files. (3) Write the PHP script that reads the file's information. (4) Add the checks: the file already exists, the file size, and the allowed formats; each check must block the upload. (5) Move the file to Uploads and tell the user that it worked. Put everything in index.php.

پرۆژەیەکی نوێی PHP لە NetBeans بکەرەوە و ناوی بنێ file_handling. (١) نوێ لە پرۆژەکەدا دروست بکە بە ناوی Uploads. (٢) HTML بۆ بنووسە. (٣) PHP بنووسە کە دەخوێنێتەوە. (٤) پشکنینەکان زیاد بکە: پێشتر هەیە، قەبارەی و شێوازە ڕێگەپێدراوەکان؛ هەر پشکنینێک دەبێت ڕابگرێت. (٥) بگوازەرەوە بۆ Uploads و بە بڵێ کە سەرکەوتوو بوو. هەموو شتێک لە index.phpدا دابنێ.

Step 1 of the lab: the Uploads folder next to index.php in the NetBeans project.هەنگاوی ١ی تاقیگەکە: Uploads لە تەنیشت ⁦index.php⁩ لە پرۆژەی NetBeansـدا.Course material
Hintئاماژە

Start from the lab's elseif chain, then add the error check, the real-type check and a random name.

لە زنجیرەی elseif ـی تاقیگەکەوە دەست پێبکە، پاشان پشکنینی هەڵە، پشکنینی جۆری ڕاستەقینە و ناوێکی هەڕەمەکی زیاد بکە.

Show answerوەڵامەکە پیشان بدە

Steps 1 to 5 together are the complete, safe upload page. Create the Uploads folder (with the .htaccess file inside it) and save the page as index.php, because the form's action is index.php. The simpler lab version (an elseif chain without the real-type check and random names) is shown in Every check must stop the upload.

هەنگاوەکانی ١ تا ٥ پێکەوە لاپەڕەی بارکردنی تەواو و سەلامەتن. Uploads دروست بکە (لەگەڵ .htaccess لەناویدا) و لاپەڕەکە وەک index.php خەزن بکە، چونکە actionی index.phpـە. وەشانە سادەترەکەی تاقیگە (زنجیرەیەکی elseif بەبێ پشکنینی جۆری ڕاستەقینە و ناوی هەڕەمەکی) لە هەموو پشکنینێک دەبێت بارکردنەکە ڕابگرێت پیشان دراوە.

index.phpPHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
<?php
// index.php - upload a photo (JPEG or PNG, at most 2 MB)
$uploadDir  = __DIR__ . "/Uploads/";       // the folder must exist
$maxSize    = 2097152;                     // 2 MB = 2 * 1024 * 1024 bytes
$extensions = ["jpeg", "jpg", "png"];      // allowed file extensions
$mimeTypes  = ["image/jpeg", "image/png"]; // allowed real file types
$errors     = [];                          // collects error messages
$message    = "";

if (isset($_POST["submit"])) {
    $file = $_FILES["image"] ?? null;

    if ($file === null || $file["error"] === UPLOAD_ERR_NO_FILE) {
        $errors[] = "Please select a file.";
    } elseif ($file["error"] !== UPLOAD_ERR_OK) {
        $errors[] = "The upload failed (error code " . $file["error"] . ").";
    } else {
        $originalName = basename($file["name"]);
        $ext = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));

        if (!in_array($ext, $extensions, true)) {
            $errors[] = "Extension not allowed. Please choose a JPEG or PNG file.";
        }
        if ($file["size"] > $maxSize) {
            $errors[] = "The file is too large. It must not be bigger than 2 MB.";
        }
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $realType = finfo_file($finfo, $file["tmp_name"]);
        if (!in_array($realType, $mimeTypes, true)) {
            $errors[] = "This file is not a real JPEG or PNG picture.";
        }

        if (empty($errors)) {
            // a new, random name: the visitor cannot choose it
            $newName = bin2hex(random_bytes(16)) . "." . $ext;
            $target  = $uploadDir . $newName;

            if (file_exists($target)) {
                $errors[] = "Sorry, this file already exists.";
            } elseif (move_uploaded_file($file["tmp_name"], $target)) {
                $message = "Success! " . htmlspecialchars($originalName) . " was uploaded.";
            } else {
                $errors[] = "Sorry, the file could not be saved.";
            }
        }
    }
}
?>
<!DOCTYPE html>
<html>
<body>
<h1>Upload a photo</h1>
<?php
foreach ($errors as $error) {
    echo "<p style=\"color: red\">$error</p>\n";
}
if ($message !== "") {
    echo "<p style=\"color: green\">$message</p>\n";
}
?>
<form action="index.php" method="post" enctype="multipart/form-data">
  Select image to upload:
  <input type="file" name="image" accept=".jpg,.jpeg,.png">
  <input type="submit" name="submit" value="Upload Image">
</form>
</body>
</html>
ExerciseڕاهێنانFind the bugs in the lab's step twoهەڵەکانی هەنگاوی دووی تاقیگەکە بدۆزەرەوە

This is step two of Lab 6 (welcome.php), exactly as printed. It does not run. Find at least six problems.

ئەمە هەنگاوی دووی تاقیگەی ٦ـە (welcome.php)، ڕێک وەک چاپ کراوە. کار ناکات. لانیکەم شەش کێشە بدۆزەرەوە.

welcome.php (lab, as printed)TEXT
<?php
$target_dir = "uploads/";
errors=””;
//get file size
$file_size=($_FILES["image"]["size"]);
variable for file name
$file_name=($_FILES["image"]["name"]);
$file_temp=($_FILES["image"]["tpm_name"]);
$file_type=($_FILES["image"]["type"]);
// get file extention
$file_ext=strtolower(end(explode('.',$_FILES['image']['name'])));
$target=$target_dir.basename($file_name);
//array of allowed extension
$extensions= array("jpeg","jpg","png");


//check if user clicks submit button
 $ if(isset($_POST["submit"])) {

   }
?>
Show answerوەڵامەکە پیشان بدە
  1. Line 3: errors=””; has no $, and ”” are curly quotes: parse error. Write $errors = []; (or "").
  2. Line 6: variable for file name is a comment without //: parse error.
  3. Line 8: "tpm_name" should be "tmp_name"; otherwise $file_temp is null and the move fails.
  4. Line 11: end(explode(...)) gives a notice; use pathinfo(). "extention" is misspelled.
  5. Line 17: $ if(...) has a stray $: parse error. The if block is also empty.
  6. $_FILES is read before checking that the form was sent, so a normal visit gives "Undefined array key" warnings. Read it inside the if.
  7. Line 2: "uploads/" does not match the folder Uploads created in step one (Linux is case-sensitive).
  8. The extra brackets in ($_FILES[...]) are harmless but unnecessary. A corrected version is Step 1.
  1. دێڕی 3: errors=””; ـی $ تێدا نییە و ”” خوارن: . بنووسە $errors = []; (یان "").
  2. دێڕی 6: variable for file name بەبێ //: .
  3. دێڕی 8: "tpm_name" دەبێت "tmp_name" بێت؛ دەنا $file_temp nullـە و گواستنەوەکە شکست دەهێنێت.
  4. دێڕی ⁦11⁩: end(explode(...)) ئاگاداری دەدات؛ pathinfo() بەکاربهێنە. «extention» بە هەڵە نووسراوە.
  5. دێڕی ⁦17⁩: $ if(...) ـی $ێکی زیادەی هەیە: . بلۆکی ifـەکەش بەتاڵە.
  6. $_FILES پێش پشکنینی ناردنی دەخوێنرێتەوە، بۆیە سەردانێکی ئاسایی «⁦Undefined array key⁩» دەدات. لەناو ifـەکەدا بیخوێنەوە.
  7. دێڕی 2: "uploads/" لەگەڵ Uploads کە لە هەنگاوی یەکەمدا دروست کرا ناگونجێت (Linux هەستیارە بە پیتی گەورە و بچووک).
  8. کەوانە زیادەکانی ($_FILES[...]) زیانیان نییە بەڵام پێویست نین. وەشانێکی ڕاستکراوە هەنگاوی ١ـە.
ExerciseڕاهێنانWhat is basename?basename چییە؟

What does basename() do in PHP? What do basename('/var/www/html/index.php') and basename('/var/www/html/index.php', '.php') return? Why is it used in upload scripts?

basename() لە PHPـدا چی دەکات؟ basename('/var/www/html/index.php') و basename('/var/www/html/index.php', '.php') چی دەگەڕێننەوە؟ بۆچی لە بەکار دێت؟

Show answerوەڵامەکە پیشان بدە

It returns the last part of a path, usually the file name: index.php. With the second argument it also removes that ending: index. In uploads it removes any folder part from a name, so that a name like ../../config.php cannot point outside the upload folder.

دوایین بەشی دەگەڕێنێتەوە، کە بەگشتی ناوی : index.php. بە دووەم ئەو کۆتاییەش لادەبات: index. لە هەر بەشێکی لە ناوێک لادەبات، بۆ ئەوەی ناوێکی وەک ../../config.php نەتوانێت ئاماژە بە دەرەوەی بکات.

ExerciseڕاهێنانAccept PDF homeworkئەرکی PDF وەربگرە

Change the complete script so that it accepts PDF files (extension pdf, real type application/pdf) of at most 5 MB, and nothing else.

تەواوەکە بگۆڕە بۆ ئەوەی PDF ( pdf، جۆری ڕاستەقینەی application/pdf) تا ٥ وەربگرێت و هیچ شتێکی تر نا.

Hintئاماژە

Only the settings at the top and the messages change.

تەنها سەرەوە و پەیامەکان دەگۆڕێن.

Show answerوەڵامەکە پیشان بدە
PHPRuns on the serverلەسەر ڕاژەکاری وێب کار دەکات
$maxSize    = 5 * 1024 * 1024;      // 5 MB = 5242880 bytes
$extensions = ["pdf"];
$mimeTypes  = ["application/pdf"];

Change the messages too ("Please choose a PDF file.", "must not be bigger than 5 MB"), the form's accept=".pdf", and check that upload_max_filesize in php.ini is at least 5M.

پەیامەکانیش بگۆڕە («⁦Please choose a PDF file⁩.»، «⁦must not be bigger than 5 MB⁩»)، accept=".pdf"ی و بپشکنە کە upload_max_filesize لە ⁦php.ini⁩دا لانیکەم ⁦5M⁩ـە.

Summary and reviewپوختە و پێداچوونەوە

  • An upload form needs method="post", enctype="multipart/form-data" and <input type="file" name="...">; file_uploads = On in php.ini.
  • PHP keeps the file in a temporary folder and describes it in $_FILES; if you do not move it, it is deleted when the request ends.
  • Check the error code, the size, the extension (pathinfo()) and the real type (finfo). Every check must block the upload.
  • move_uploaded_file($tmp, $target) takes two arguments and returns true or false.
  • Save under a new unique name, outside the web root or in a folder where scripts cannot run.
  • Two methods: a folder plus the path in the database (usual), or the bytes in a BLOB column, always with a prepared statement.
  • پێویستی بە method="post"، enctype="multipart/form-data" و <input type="file" name="..."> هەیە؛ file_uploads = On لە ⁦php.ini⁩دا.
  • PHP لە کاتیدا ڕادەگرێت و لە $_FILESدا وەسفی دەکات؛ ئەگەر نەیگوازیتەوە، لە کۆتایی دەسڕدرێتەوە.
  • کۆدی ، قەبارە، (pathinfo()) و جۆری ڕاستەقینە (finfo) بپشکنە. هەموو پشکنینێک دەبێت ڕابگرێت.
  • move_uploaded_file($tmp, $target) دوو وەردەگرێت و true یان false دەگەڕێنێتەوە.
  • بە ناوێکی نوێی بێهاوتا خەزنی بکە، لە دەرەوەی ڕەگی وێب یان لە کە تێیدا جێبەجێ نابێت.
  • دوو ڕێگا: لەگەڵ لە (باو)، یان لە BLOBـدا، هەمیشە بە .
Review questionsپرسیارەکانی پێداچوونەوە
What must you take into consideration to upload a file with <input type="file">?بۆ بارکردنی فایل بە ⁦<input type="file">⁩ دەبێت ئاگات لە چی بێت؟

Use the POST method, add enctype="multipart/form-data" to the form (without it the file is not uploaded), and make sure file_uploads = On in php.ini.

بەکاربهێنە، ⁦enctype="multipart/form-data⁩" بۆ زیاد بکە (بەبێ ئەو بار ناکرێت) و دڵنیابە کە ⁦file_uploads = On⁩ لە ⁦php.ini⁩دا.

What are the two file-upload methods?دوو ڕێگاکەی بارکردنی فایل چین؟

Copy the file to a local folder and store its path in the database, or store the file itself in the database as a BLOB.

بۆ ناوخۆیی کۆپی بکە و لە هەڵبگرە، یان خۆی لە وەک BLOB هەڵبگرە.

Why does PHP save an uploaded file into a temporary directory?بۆچی PHP فایلی بارکراو لە فۆڵدەرێکی کاتیدا خەزن دەکات؟

So that the script can check the file before deciding to keep it. The temporary file is a holding area: if the script does not move it with move_uploaded_file(), PHP deletes it when the request ends. PHP itself does not scan for viruses; the checks are the developer's job.

بۆ ئەوەی بتوانێت پێش بڕیاردان لەسەر هەڵگرتنی، بپشکنێت. شوێنێکی ڕاگرتنە: ئەگەر بە ⁦move_uploaded_file()⁩ نەیگوازێتەوە، PHP لە کۆتایی دەیسڕێتەوە. PHP خۆی بۆ ڤایرۆس ناپشکنێت؛ پشکنینەکان ئەرکی گەشەپێدەرن.

What do name, size, tmp_name, type and error in $_FILES hold?name، size، ⁦tmp_name⁩، type و error لە ⁦$_FILES⁩دا چی هەڵدەگرن؟

The original file name, the size in bytes, the temporary file's path, the type claimed by the browser, and the upload error code (0 = OK).

ناوی ڕەسەنی ، قەبارە بە ، ، ئەو جۆرەی دەیڵێت و کۆدی (⁦0⁩ = باش).

Why is checking the extension not enough?بۆچی پشکنینی پاشگری فایل بەس نییە؟

Anyone can rename a file. Check the real type of the content with finfo (and save under a new name in a place where scripts cannot run).

هەر کەسێک دەتوانێت ناوی بگۆڕێت. جۆری ڕاستەقینەی ناوەڕۆکەکە بە finfo بپشکنە (و بە ناوێکی نوێ لە شوێنێکدا خەزنی بکە کە تێیدا جێبەجێ نابێت).

What is basename in PHP?basename لە PHPـدا چییە؟

A function that returns the last part of a path, usually the file name; with a second argument it also removes that file extension.

کە دوایین بەشی دەگەڕێنێتەوە، کە بەگشتی ناوی ؛ بە دووەم ئەو پاشگرەش لادەبات.

Why did the slide's complete upload script save virus.exe?بۆچی دەسنووسە تەواوەکەی سلایدەکە ⁦virus.exe⁩ ـی خەزن کرد؟

Its checks only echoed messages and never added to $errors, so empty($errors) was always true and the file was always moved.

پشکنینەکانی تەنها پەیامیان echo دەکرد و هەرگیز هیچیان بۆ ⁦$errors⁩ زیاد نەدەکرد، بۆیە ⁦empty($errors)⁩ هەمیشە ڕاست بوو و هەمیشە دەگوازرایەوە.

Videoڤیدیۆ

Watch a videoسەیری ڤیدیۆیەک بکە

A video that viewers liked a lot and praised in their comments, chosen for this lesson.ڤیدیۆیەک کە بینەران زۆریان پێ خۆش بووە و لە کۆمێنتەکانیاندا ستایشیان کردووە، بۆ ئەم وانەیە هەڵبژێردراوە.

PHP File Uploads | The Complete Guide to Uploading Files Using PHPDave Hollingworth · Englishئینگلیزی · 62K viewsبینین · 1.1K likesلایک · Partبەشی 0:00–10:30 (ofلە 19:28)

Builds an upload form and script step by step: what $_FILES holds, php.ini settings, every upload error code, and a file-size limit.

هەنگاو بە هەنگاو و دروست دەکات: $_FILES چی تێدایە، ڕێکخستنەکانی ، هەموو کۆدەکانی و سنووری قەبارەی .

Watch 0:00–10:30: form, $_FILES, php.ini, error codes, size limit.

لە ⁦0:00⁩ تا ⁦10:30⁩ سەیر بکە: ، $_FILES، ، کۆدەکانی و سنووری قەبارە.

Lesson complete!وانەکە تەواو بوو!

Well done. Review the key terms, then go on to the next lesson.دەستخۆش. سەیرێکی زاراوە سەرەکییەکان بکەرەوە، پاشان بڕۆ بۆ وانەی داهاتوو.

Key termsزاراوە سەرەکییەکان

Next lessonوانەی داهاتوو

Databases and SQL basicsبنکەدراوەکان و بنەماکانی SQL

References and further readingسەرچاوەکان و خوێندنەوەی زیاتر

This lecture is a first edition. The Kurdish text and terminology are waiting for review by Kurdish IT teachers.ئەم وانەیە چاپی یەکەمە. دەقە کوردییەکە و زاراوەکانی چاوەڕێی پێداچوونەوەی مامۆستایانی کوردی بواری IT ن.