chengkun
2025-06-05 4080b5997b38ca84b3b203c7101dcadb97b76925
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2025 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
declare(strict_types=1);
 
namespace think\response;
 
use think\Exception;
use think\Response;
 
/**
 * File Response
 */
class File extends Response
{
    protected $expire = 360;
    protected $name;
    protected $mimeType;
    protected $isContent = false;
    protected $force     = true;
 
    public function __construct($data = '', int $code = 200)
    {
        $this->init($data, $code);
    }
 
    /**
     * 处理数据
     * @access protected
     * @param  mixed $data 要处理的数据
     * @return mixed
     * @throws \Exception
     */
    protected function output($data)
    {
        if (!$this->isContent && !is_file($data)) {
            throw new Exception('file not exists:' . $data);
        }
 
        while (ob_get_level() > 0) {
            ob_end_clean();
        }
 
        if (!empty($this->name)) {
            $name = $this->name;
        } else {
            $name = !$this->isContent ? pathinfo($data, PATHINFO_BASENAME) : '';
        }
        $name = urlencode($name); // 支持中文名称
 
        if ($this->isContent) {
            $mimeType = $this->mimeType;
            $size     = strlen($data);
        } else {
            $mimeType = $this->getMimeType($data);
            $size     = filesize($data);
        }
 
        $this->header['Pragma']                    = 'public';
        $this->header['Content-Type']              = $mimeType ?: 'application/octet-stream';
        $this->header['Cache-control']             = 'max-age=' . $this->expire;
        $this->header['Content-Disposition']       = ($this->force ? 'attachment; ' : '') . 'filename="' . $name . '";' . "filename* = UTF-8''{$name}";
        $this->header['Content-Length']            = $size;
        $this->header['Content-Transfer-Encoding'] = 'binary';
        $this->header['Expires']                   = gmdate("D, d M Y H:i:s", time() + $this->expire) . ' GMT';
 
        $this->lastModified(gmdate('D, d M Y H:i:s', time()) . ' GMT');
 
        return $this->isContent ? $data : file_get_contents($data);
    }
 
    /**
     * 设置是否为内容 必须配合mimeType方法使用
     * @access public
     * @param  bool $content
     * @return $this
     */
    public function isContent(bool $content = true)
    {
        $this->isContent = $content;
        return $this;
    }
 
    /**
     * 设置有效期
     * @access public
     * @param  integer $expire 有效期
     * @return $this
     */
    public function expire(int $expire)
    {
        $this->expire = $expire;
        return $this;
    }
 
    /**
     * 设置文件类型
     * @access public
     * @param  string $filename 文件名
     * @return $this
     */
    public function mimeType(string $mimeType)
    {
        $this->mimeType = $mimeType;
        return $this;
    }
 
    /**
     * 设置文件强制下载
     * @access public
     * @param  bool $force 强制浏览器下载
     * @return $this
     */
    public function force(bool $force)
    {
        $this->force = $force;
        return $this;
    }
 
    /**
     * 获取文件类型信息
     * @access public
     * @param  string $filename 文件名
     * @return string
     */
    protected function getMimeType(string $filename): string
    {
        if (!empty($this->mimeType)) {
            return $this->mimeType;
        }
 
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
 
        return finfo_file($finfo, $filename);
    }
 
    /**
     * 设置下载文件的显示名称
     * @access public
     * @param  string $filename 文件名
     * @param  bool   $extension 后缀自动识别
     * @return $this
     */
    public function name(string $filename, bool $extension = true)
    {
        $this->name = $filename;
 
        if ($extension && !str_contains($filename, '.')) {
            $this->name .= '.' . pathinfo($this->data, PATHINFO_EXTENSION);
        }
 
        return $this;
    }
}