Skip to content

Commit

Permalink
增强发送文件功能,支持文件名、ContentType指定或自动识别
Browse files Browse the repository at this point in the history
  • Loading branch information
Yurunsoft committed Sep 8, 2021
1 parent 688b89a commit fd3dae0
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 9 deletions.
32 changes: 28 additions & 4 deletions src/Http/Message/WorkermanResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Imi\Workerman\Http\Message;

use Imi\Server\Http\Message\Response;
use Imi\Util\Http\Consts\MediaType;
use Imi\Util\Http\Consts\StatusCode;
use Workerman\Connection\TcpConnection;
use Workerman\Worker;
Expand Down Expand Up @@ -119,14 +120,37 @@ public function send(): self
/**
* 发送文件,一般用于文件下载.
*
* @param string $filename 要发送的文件名称,文件不存在或没有访问权限sendfile会失败
* @param int $offset 上传文件的偏移量,可以指定从文件的中间部分开始传输数据。此特性可用于支持断点续传。
* @param int $length 发送数据的尺寸,默认为整个文件的尺寸
* @param string $filename 要发送的文件名称,文件不存在或没有访问权限sendfile会失败
* @param string|null $contentType Content-Type 响应头,不填则自动识别
* @param string|null $outputFileName 下载文件名,不填则自动识别,如:123.zip
* @param int $offset 上传文件的偏移量,可以指定从文件的中间部分开始传输数据。此特性可用于支持断点续传。
* @param int $length 发送数据的尺寸,默认为整个文件的尺寸
*
* @return static
*/
public function sendFile(string $filename, int $offset = 0, int $length = 0): self
public function sendFile(string $filename, ?string $contentType = null, ?string $outputFileName = null, int $offset = 0, int $length = 0): self
{
if (null === $outputFileName)
{
$outputFileName = basename($filename);
}
$this->setHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . rawurlencode($outputFileName));

if (null === $contentType)
{
$outputFileNameExt = pathinfo($outputFileName, \PATHINFO_EXTENSION);
$contentType = MediaType::getContentType($outputFileNameExt);
if (MediaType::APPLICATION_OCTET_STREAM === $contentType)
{
$fileNameExt = pathinfo($filename, \PATHINFO_EXTENSION);
if ($fileNameExt !== $outputFileNameExt)
{
$contentType = MediaType::getContentType($fileNameExt);
}
}
}
$this->setHeader('Content-Type', $contentType);

$this->sendHeaders();
if ($this->isBodyWritable())
{
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/AppServer/ApiServer/Controller/IndexController.php
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,9 @@ public function redirect()
*
* @return mixed
*/
public function download()
public function download(?string $contentType = null, ?string $outputFileName = null)
{
return RequestContext::get('response')->sendFile(__FILE__);
return RequestContext::get('response')->sendFile(__FILE__, $contentType, $outputFileName);
}

/**
Expand Down
22 changes: 21 additions & 1 deletion tests/unit/AppServer/Tests/Http/ResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Imi\Workerman\Test\AppServer\Tests\Http;

use Imi\Util\Http\Consts\MediaType;
use Imi\Util\Http\Consts\StatusCode;
use Yurun\Util\HttpRequest;

Expand Down Expand Up @@ -107,8 +108,27 @@ public function testRedirect(): void
*/
public function testDownload(): void
{
$content = file_get_contents(\dirname(__DIR__, 2) . '/ApiServer/Controller/IndexController.php');

$http = new HttpRequest();
$response = $http->get($this->host . 'download');
$this->assertEquals(file_get_contents(\dirname(__DIR__, 2) . '/ApiServer/Controller/IndexController.php'), $response->body());
$this->assertEquals($content, $response->body());
$this->assertEquals(MediaType::APPLICATION_OCTET_STREAM, $response->getHeaderLine('content-type'));
$this->assertEquals('attachment; filename*=UTF-8\'\'IndexController.php', $response->getHeaderLine('content-disposition'));

$response = $http->get($this->host . 'download', [
'outputFileName' => '测试.jpg',
]);
$this->assertEquals($content, $response->body());
$this->assertEquals(MediaType::IMAGE_JPEG, $response->getHeaderLine('content-type'));
$this->assertEquals('attachment; filename*=UTF-8\'\'' . rawurlencode('测试.jpg'), $response->getHeaderLine('content-disposition'));

$response = $http->get($this->host . 'download', [
'contentType' => MediaType::IMAGE_PNG,
'outputFileName' => '测试.jpg',
]);
$this->assertEquals($content, $response->body());
$this->assertEquals(MediaType::IMAGE_PNG, $response->getHeaderLine('content-type'));
$this->assertEquals('attachment; filename*=UTF-8\'\'' . rawurlencode('测试.jpg'), $response->getHeaderLine('content-disposition'));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,9 @@ public function redirect()
*
* @return mixed
*/
public function download()
public function download(?string $contentType = null, ?string $outputFileName = null)
{
return RequestContext::get('response')->sendFile(__FILE__);
return RequestContext::get('response')->sendFile(__FILE__, $contentType, $outputFileName);
}

/**
Expand Down

0 comments on commit fd3dae0

Please sign in to comment.