Symfony 2 使用 OneupUploaderBundle 上傳檔案中文命名問題的解決方式

在Symfony框架開發的項目上,需要製作上傳檔案功能,很多時為了加快開發速度,都會使用第三方插件。

提供上傳檔案功能這一類的插件非常多,在這次項目上使用了OneupUploaderBundle這一個插件。

OneupUploaderBundle提供了一個命名上傳檔案的介面,預設情況下,上載的檔案會使用uniqid函數處理。

oneup/uploader-bundle/Oneup/UploaderBundle/Uploader/Naming/UniqidNamer.php

public function name(FileInterface $file)
{
    return sprintf('%s.%s', uniqid(), $file->getExtension());
}

但這次需求上,上傳的檔案名稱需要和原檔名相同,所以自訂了一個namer介面。

public function name(FileInterface $file)
{
   $suffix = '';
   $name = $file->getClientOriginalName();
   $name = substr($name,0, mb_strrpos($name, '.')); //取得檔案名稱

   $number = 2; //如檔名已存在,則於檔名後加入一個數值
   while(true) {
      $filePath = sprintf('%s%s%s.%s',
         $this->container->getParameter('oneup_fineuploader_directory'),
         $name,
         $suffix,
         $file->getExtension()
      );

      if(file_exists($filePath)) {
         $suffix = '(' . $number .')';
      } else {
         break;
      }
      $number++;
   }

   return sprintf('%s%s.%s',
      $name,
      $suffix,
      $file->getExtension()
   );
}

但測試時發現上傳的檔名開頭如果為中文時(除了英文和中文,其它語言沒有測試),上傳後在系統找回該檔案會沒有了中文的部份。追查後發現插件於命名函數裹使用了basename函數,因為basename函數依賴於區域設置,如果是多字節名稱返回為空,可以通過setlocale函數作如下設置。

oneup/uploader-bundle/Oneup/UploaderBundle/Uploader/Storage/FilesystemStorage.php

public function upload(FileInterface $file, $name, $path = null)
{
    $path = is_null($path) ? $name : sprintf('%s/%s', $path, $name);
    $path = sprintf('%s/%s', $this->directory, $path);

    // now that we have the correct path, compute the correct name
    // and target directory
    $targetName = basename($path);
    $targetDir  = dirname($path);

    $file = $file->move($targetDir, $targetName);

    return $file;
}

所以最後我選擇在Symfony的入口加入這個設置,中文命名的檔案上傳亦沒有問題。

web/app.php
web/app_dev.php

setlocale(LC_ALL, 'zh_TW.UTF-8');

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *

*

驗證碼 * Time limit is exhausted. Please reload CAPTCHA.

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料