【问题标题】:laravel 4 The filename fallback must only contain ASCII characterslaravel 4 文件名后备只能包含 ASCII 字符
【发布时间】:2013-12-04 08:21:06
【问题描述】:

我的文件包含 UTF-8(希腊)字符,我无法下载它。我正在使用 laravel 4。这是我的代码:

//下载

Route::get('file/download', function()
{
$file = 'uploads/πτυχιακή.odt';
return Response::download($file);
});

我收到以下错误(invalidArgumentException)消息:文件名回退必须只包含 ASCII 字符

关于如何解决这个问题的任何想法..?

【问题讨论】:

  • 我会重命名这些文件......让它们在某些不同的层面上可能会让人头疼。
  • Laravel 论坛上的同样问题,除了重命名文件之外,没有真正的解决方案。 forums.laravel.io/viewtopic.php?pid=61493

标签: php apache symfony laravel-4


【解决方案1】:

这是 Response::download 函数中的一个错误。将其更改为:

// File: vendor/laravel/framework/src/Illuminate/Support/Facades/Response.php

public static function download($file, $name = null, array $headers = array(), $disposition = 'attachment')
{
    $response = new BinaryFileResponse($file, 200, $headers, true);

    if (is_null($name))
    {
        $name = basename($file);
    }

   return $response->setContentDisposition($disposition, $name, Str::ascii($name));
}

https://github.com/laravel/framework/pull/4296

Laravel 5

在 Laravel 5 中,您可以扩展 \Illuminate\Routing\ResponseFactory 类并覆盖 download() 方法。然后,在 ServiceProvider 中,将您的自定义 ResponseFactory 注册为默认值:

// We extends \Illuminate\Routing\ResponseFactory class, that implements Illuminate\Contracts\Routing\ResponseFactory

$this->app->singleton('Illuminate\Contracts\Routing\ResponseFactory', function ($app) {
    return new MyCustomResponseFactoryExtendedFromResponseFactory($app['Illuminate\Contracts\View\Factory'], $app['redirect']);
});

这样做,您可以使用默认方法(Response::json()、respose()->view() 等)和您的自定义方法同理:Response::download(), _response()->download

【讨论】:

    【解决方案2】:

    正如http://laravel.com/docs/responses#special-responses中所述:

    注意:管理文件下载的 Symfony HttpFoundation 需要 正在下载的文件具有 ASCII 文件名。

    如果我理解正确,理想情况下,文件名应该在上传过程中使用 ascii 文件名存储,然后返回:

    return Response::download(<ascii_filename>);
    

    如果文件名与上传时不同是可以接受的。

    但是,如果文件名不得更改,则文件的下载应触发:

    return Response::download(<ascii_filename>, <original_file_name>);
    

    这意味着在上传过程中存储文件后需要跟踪原始文件名。这可以通过简化文件名并将原始文件名存储在数据库中来实现,也可以通过将文件名存储为编码后的名称以使其可以转换回其原始名称来实现。

    跟踪数据库中的原始文件名可以简化文件名,使其易于识别(例如,'hallå där.txt' -> 'halla dar.txt')。

    但是,使用数据库并不总是一种选择。有不同的方法可以将 UTF-8 或 ISO-8859-1 字符串转换为 ASCII,并且可以将它们转换回来(例如 base64_encode / base64_decode、mb_convert_encoding 等),每种方法都有优缺点(例如,取决于您是否希望能够以可识别的名称存储文件)。

    【讨论】:

    • 此解决方案不起作用,即使将 utf-8 名称作为第二个参数传递给 downlaod 方法,返回的文件名也会更改为其他名称
    • 我使用 mb_convert_encoding 将原始文件名编码为 ASCII。它有效!
    猜你喜欢
    • 1970-01-01
    • 2014-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-27
    • 1970-01-01
    相关资源
    最近更新 更多