CodeIgniter4 使用文件上傳類(lèi)

2020-08-17 17:04 更新

在 CodeIgniter 中通過(guò)表單使用文件上傳功能將會(huì)比直接使用 PHP 的 $_FILES 數(shù)組更加簡(jiǎn)單和安全。其將繼承 文件類(lèi) 并獲取該類(lèi)的所有功能。

注解

這和 CodeIgniter 的上一版本的文件上傳類(lèi)不同。這次提供了一個(gè)原生接口及一些小功能來(lái)上傳文件。上傳類(lèi)將在最終版的時(shí)提供。

訪問(wèn)文件

所有文件

當(dāng)你上傳文件時(shí),PHP 可以在本地使用全局?jǐn)?shù)組 $_FILES 來(lái)訪問(wèn)這些文件。當(dāng)你同時(shí)上傳多個(gè)文件時(shí),這個(gè)數(shù)組存在一些不可忽視的缺點(diǎn)和很多開(kāi)發(fā)者沒(méi)有意識(shí)到的安全方面的潛在缺陷。CodeIgniter 通過(guò)一個(gè)公共接口來(lái)規(guī)范你對(duì)文件的使用,從而改善這些問(wèn)題。

通過(guò)當(dāng)前的 IncomingRequest 實(shí)例來(lái)訪問(wèn)文件。使用 getFiles() 方法來(lái)獲取本次請(qǐng)求中上傳的所有文件。方法將會(huì)返回由 CodeIgniter\HTTP\Files\UploadedFile 實(shí)例表示的文件數(shù)組:

  1. $files = $this->request->getFiles();

當(dāng)然,有很多種方式來(lái)為文件 input 標(biāo)簽命名,除了最簡(jiǎn)外任何其他任何命名方式都可能產(chǎn)生奇怪的結(jié)果。數(shù)組將會(huì)以你期望的方式返回。使用最簡(jiǎn)方式,一個(gè)單文件提交表單可能會(huì)是這樣:

  1. <input type="file" name="avatar" />

其將會(huì)返回一個(gè)簡(jiǎn)單的數(shù)組像是:

  1. [
  2. 'avatar' => // UploadedFile instance
  3. ]

如果你在標(biāo)簽名稱(chēng)中使用數(shù)組表示法,input 標(biāo)簽將看上去像是這樣:

  1. <input type="file" name="my-form[details][avatar]" />

getFiles() 方法返回的數(shù)組看上去將像是這樣:

  1. [
  2. 'my-form' => [
  3. 'details' => [
  4. 'avatar' => // UploadedFile instance
  5. ]
  6. ]
  7. ]

在某些情況下,你可以指定一組文件元素來(lái)上傳:

  1. Upload an avatar: <input type="file" name="my-form[details][avatars][]" />
  2. Upload an avatar: <input type="file" name="my-form[details][avatars][]" />

在這種情況下,返回的文件數(shù)組將會(huì)像是這樣:

  1. [
  2. 'my-form' => [
  3. 'details' => [
  4. 'avatar' => [
  5. 0 => /* UploadedFile instance */,
  6. 1 => /* UploadedFile instance */
  7. ]
  8. ]
  9. ]

單個(gè)文件

如果你只需要訪問(wèn)單個(gè)文件,你可以使用 getFile() 方法來(lái)直接獲取文件實(shí)例。其將會(huì)返回一個(gè) CodeIgniter\HTTP\Files\UploadedFile 實(shí)例:

最簡(jiǎn)使用

使用最簡(jiǎn)方式,一個(gè)單文件提交表單可能會(huì)是這樣:

  1. <input type="file" name="userfile" />

其將會(huì)返回一個(gè)簡(jiǎn)單的文件實(shí)例像是:

  1. $file = $this->request->getFile('userfile');

數(shù)組表示法

如果你在標(biāo)簽名稱(chēng)中使用數(shù)組表示法,input 標(biāo)簽將看上去像是這樣:

  1. <input type="file" name="my-form[details][avatar]" />

這樣來(lái)獲取文件實(shí)例:

  1. $file = $this->request->getFile('my-form.details.avatar');

多文件

  1. <input type="file" name="images[]" multiple />

在控制器中::

  1. if($imagefile = $this->request->getFiles()) {
  2. foreach($imagefile[‘images’] as $img) {
  3. if ($img->isValid() && ! $img->hasMoved()) {
  4. $newName = $img->getRandomName(); $img->move(WRITEPATH.’uploads’, $newName);
  5. }
  6. }
  7. }

循環(huán)中的 images 是表單中的字段名稱(chēng)

如果多個(gè)文件使用相同名稱(chēng)提交,你可以使用 getFile() 去逐個(gè)獲取每個(gè)文件:: 在控制器中:

  1. $file1 = $this->request->getFile('images.0');
  2. $file2 = $this->request->getFile('images.1');

另外一個(gè)例子:

  1. Upload an avatar: <input type="file" name="my-form[details][avatars][]" />
  2. Upload an avatar: <input type="file" name="my-form[details][avatars][]" />

在控制器中:

  1. $file1 = $this->request->getFile('my-form.details.avatars.0');
  2. $file2 = $this->request->getFile('my-form.details.avatars.1');

注解

使用 getFiles() 更合適。

使用文件

一旦你獲取到了 UploadedFile 實(shí)例,你可以以安全的方式檢索到文件的信息,還能將文件移動(dòng)到新的位置。

驗(yàn)證文件

你可以調(diào)用 isValid() 方法來(lái)檢查文件是否是通過(guò) HTTP 無(wú)誤上傳的:

  1. if (! $file->isValid())
  2. {
  3. throw new RuntimeException($file->getErrorString().'('.$file->getError().')');
  4. }

如這個(gè)例子所見(jiàn),如果一個(gè)文件產(chǎn)生一個(gè)上傳錯(cuò)誤,你可以通過(guò) getError()getErrorString() 方法獲取錯(cuò)誤碼(一個(gè)整數(shù))和錯(cuò)誤消息。通過(guò)此方法可以發(fā)現(xiàn)以下錯(cuò)誤:

  • 文件大小超過(guò)了 upload_max_filesize 配置的值。
  • 文件大小超過(guò)了表單定義的上傳限制。
  • 文件僅部分被上傳。
  • 沒(méi)有文件被上傳。
  • 無(wú)法將文件寫(xiě)入磁盤(pán)。
  • 無(wú)法上傳文件:缺少臨時(shí)目錄。
  • PHP擴(kuò)展阻止了文件上傳。

文件名稱(chēng)

getName()

你可以通過(guò) getName() 提取到客戶端提供的文件的原始名稱(chēng)。其通常是由客戶端發(fā)送的文件名,不應(yīng)受信。如果文件已經(jīng)被移動(dòng),將返回移動(dòng)文件的最終名稱(chēng):

  1. $name = $file->getName();

getClientName()

總是返回由客戶端發(fā)送的上傳文件的原始名稱(chēng),即使文件已經(jīng)被移動(dòng)了:

  1. $originalName = $file->getClientName();

getTempName()

要獲取在上傳期間產(chǎn)生的臨時(shí)文件的全路徑,你可以使用 getTempName() 方法:

  1. $tempfile = $file->getTempName();

其他文件信息

getClientExtension()

基于上傳文件的名稱(chēng),返回原始文件擴(kuò)展名。這不是一個(gè)值得信賴(lài)的來(lái)源。對(duì)于可信的版本,請(qǐng)使用 getExtension() 來(lái)代替:

  1. $ext = $file->getClientExtension();

getClientType()

返回由客戶端提供的文件的媒體類(lèi)型(mime type)。這不是一個(gè)值得信賴(lài)的值,對(duì)于可信的版本,請(qǐng)使用 getType() 來(lái)代替:

  1. $type = $file->getClientType();
  2. echo $type; // image/png

移動(dòng)文件

每個(gè)文件都可以使用恰如其名的 move() 方法來(lái)移動(dòng)到新的位置。使用第一個(gè)參數(shù)為目標(biāo)目錄來(lái)移動(dòng)文件:

  1. $file->move(WRITEPATH.'uploads');

默認(rèn)的,將使用文件原始名稱(chēng)。你可以指定一個(gè)新的文件名稱(chēng)作為第二個(gè)參數(shù)傳遞給方法。

$newName = $file-&getRandomName(); $file-&move(WRITEPATH.’uploads’, $newName);

一旦文件被移除,將刪除臨時(shí)文件。你可以通過(guò) hasMoved() 方法來(lái)檢查文件是否已經(jīng)被移動(dòng)了,返回布爾值:

  1. if ($file->isValid() && ! $file->hasMoved())
  2. {
  3. $file->move($path);
  4. }
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)