如何在PHP中设置Server-Sent Events?
时间: 2024-11-30 22:11:41 浏览: 57
在PHP中设置Server-Sent Events (SSE) 需要在服务器端创建一个持续输出数据的脚本。下面是一个简单的例子:
```php
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
// 模拟数据生成
$data = array(
'event' => 'message', // 数据类型
'data' => 'Hello from server!'
);
while (true) {
echo "data: {$data['data']}\n\n"; // 输出JSON格式的数据,每行结束符为'\n\n'
sleep(1); // 每秒发送一次数据,这里只是为了示例,实际应用可以根据需要调整延迟时间
}
?>
```
以上代码首先设置了响应头信息,告诉浏览器这是一个 Server-Sent Events 的请求。然后进入一个无限循环,在循环内部模拟数据生成,并以指定间隔发送给客户端。
客户端接收这部分数据后,会自动解析成事件流形式,并显示在页面上。
相关问题
Server-Sent Events demo
以下是一个基本的Server-Sent Events示例:
HTML代码:
```
<!DOCTYPE html>
<html>
<head>
<title>Server-Sent Events Demo</title>
<meta charset="UTF-8">
</head>
<body>
<div id="sse">
<h1>Server-Sent Events Demo</h1>
</div>
<script>
if(typeof(EventSource)!=="undefined") {
var source = new EventSource("demo_sse.php");
source.onmessage = function(event) {
document.getElementById("sse").innerHTML += event.data + "<br>";
};
} else {
document.getElementById("sse").innerHTML = "Sorry, your browser does not support server-sent events...";
}
</script>
</body>
</html>
```
PHP代码:
```
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$time = date('r');
echo "data: The server time is: {$time}\n\n";
flush();
?>
```
在上面的示例中,HTML页面通过JavaScript创建一个新的EventSource对象,该对象连接到一个名为“demo_sse.php”的PHP文件。PHP文件发送一个包含服务器时间的数据消息,并在每次发送消息后进行缓冲刷新,以确保消息立即传输给客户端。在HTML页面中,每当从服务器接收到新的消息时,将其添加到页面中的“sse”元素中。
我需要你帮我修复 能够让ttf这种字体 在安卓小程序成功被加载 项目是tp5 在宝塔上 , 运行目录是public 开启了伪静态 字体文件路径是 https://yinzhang.jinshelby.com/xcx/font/kaiti2.ttf 这是我的nginx配置: user www www; worker_processes auto; error_log /www/wwwlogs/nginx_error.log crit; pid /www/server/nginx/logs/nginx.pid; worker_rlimit_nofile 100000; stream { log_format tcp_format '$time_local|$remote_addr|$protocol|$status|$bytes_sent|$bytes_received|$session_time|$upstream_addr|$upstream_bytes_sent|$upstream_bytes_received|$upstream_connect_time'; access_log /www/wwwlogs/tcp-access.log tcp_format; error_log /www/wwwlogs/tcp-error.log; include /www/server/panel/vhost/nginx/tcp/*.conf; } events { use epoll; worker_connections 51200; multi_accept on; } http { include mime.types; # 已经包含标准字体类型定义 # 修正 MIME 类型定义(移除重复项) # 手动添加字体类型映射 types { font/truetype ttf; font/opentype otf; # application/font-woff woff; # application/font-woff2 woff2; } # 确保默认类型设置正确 default_type application/octet-stream; } # 移除重复的 default_type # default_type application/font-sfnt; // 注释掉这行 default_type application/octet-stream; #include luawaf.conf; include proxy.conf; server_names_hash_bucket_size 512; client_header_buffer_size 32k; large_client_header_buffers 4 32k; client_max_body_size 300m; sendfile on; tcp_nopush on; keepalive_timeout 60; tcp_nodelay on; fastcgi_connect_timeout 3000; fastcgi_send_timeout 3000; fastcgi_read_timeout 3000; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 256k; fastcgi_intercept_errors on; gzip on; gzip_min_length 1k; gzip_buffers 4 16k; gzip_http_version 1.1; gzip_comp_level 2; gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml; gzip_vary on; gzip_proxied expired no-cache no-store private auth; gzip_disable "MSIE [1-6]\."; limit_conn_zone $binary_remote_addr zone=perip:10m; limit_conn_zone $server_name zone=perserver:10m; server_tokens off; access_log off; server { listen 888; server_name phpmyadmin; index index.html index.htm index.php; root /www/server/phpmyadmin; location ~ /tmp/ { return 403; } #error_page 404 /404.html; include enable-php.conf; location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; } location ~* ^/xcx/font/.*\.(ttf|otf|woff|woff2)$ { root /www/wwwroot/yinzhang.jinshelby.com/public; # 添加详细日志 access_log /www/wwwlogs/font_access.log; error_log /www/wwwlogs/font_error.log notice; # # 强制设置正确的 Content-Type(重点) # if ($uri ~ \.ttf$) { # add_header Content-Type "font/truetype" always; # } # if ($uri ~ \.otf$) { # add_header Content-Type "font/opentype" always; # } # if ($uri ~ \.woff$) { # add_header Content-Type "font/woff" always; # } # if ($uri ~ \.woff2$) { # add_header Content-Type "font/woff2" always; # } # CORS 支持 if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'Range'; add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain charset=UTF-8'; add_header 'Content-Length' 0; return 204; } add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Range' always; add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always; # 缓存控制 expires 1y; add_header Cache-Control "public, max-age=31536000, immutable"; # 字节范围支持(安卓必需) add_header Accept-Ranges bytes; try_files $uri = 404; } location ~ .*\.(js|css)?$ { expires 12h; } location ~ /\. { deny all; } access_log /www/wwwlogs/access.log; } include /www/server/panel/vhost/nginx/*.conf; } 这是网站的配置: server { listen 80; listen 443 ssl http2 ; server_name yinzhang.jinshelby.com; index index.php index.html index.htm default.php default.htm default.html; root /www/wwwroot/yinzhang.jinshelby.com/public; #CERT-APPLY-CHECK--START # 用于SSL证书申请时的文件验证相关配置 -- 请勿删除 include /www/server/panel/vhost/nginx/well-known/yinzhang.jinshelby.com.conf; #CERT-APPLY-CHECK--END #SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则 #error_page 404/404.html; #HTTP_TO_HTTPS_START if ($server_port !~ 443){ rewrite ^(/.*)$ https://$host$1 permanent; } #HTTP_TO_HTTPS_END ssl_certificate /www/server/panel/vhost/cert/yinzhang.jinshelby.com/fullchain.pem; ssl_certificate_key /www/server/panel/vhost/cert/yinzhang.jinshelby.com/privkey.pem; ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; ssl_prefer_server_ciphers on; ssl_session_tickets on; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; add_header Strict-Transport-Security "max-age=31536000"; error_page 497 https://$host$request_uri; #SSL-END #引用重定向规则,注释后配置的重定向代理将无效 include /www/server/panel/vhost/nginx/redirect/yinzhang.jinshelby.com/*.conf; #ERROR-PAGE-START 错误页配置,可以注释、删除或修改 #error_page 502 /502.html; #ERROR-PAGE-END #PHP-INFO-START PHP引用配置,可以注释或修改 include enable-php-74.conf; #PHP-INFO-END #REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效 include /www/server/panel/vhost/rewrite/yinzhang.jinshelby.com.conf; #REWRITE-END #禁止访问的文件或目录 location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|\.svn|\.project|LICENSE|README.md) { return 404; } #一键申请SSL证书验证目录相关设置 location ~ \.well-known{ allow all; } #禁止在证书验证目录放入敏感文件 if ( $uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$" ) { return 403; } location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|ttf)$ { expires 30d; error_log /dev/null; access_log /dev/null; } location ~ .*\.(js|css)?$ { expires 12h; error_log /dev/null; access_log /dev/null; } access_log /www/wwwlogs/yinzhang.jinshelby.com.log; error_log /www/wwwlogs/yinzhang.jinshelby.com.error.log; } 这是我测试字体的返回结果: [root@iZ2ze39ozhhd4olqy1dh88Z ~]# curl -I https://yinzhang.jinshelby.com/xcx/font/st.ttf HTTP/2 200 server: nginx date: Fri, 04 Jul 2025 08:21:33 GMT content-type: application/octet-stream content-length: 7001536 last-modified: Tue, 24 Jun 2025 09:10:03 GMT etag: "685a6b6b-6ad5c0" expires: Sun, 03 Aug 2025 08:21:33 GMT cache-control: max-age=2592000 strict-transport-security: max-age=31536000 accept-ranges: bytes
<think>我们正在处理两个主要问题:
1. 修复安卓小程序中TTF字体无法正确加载的问题。
2. 优化Nginx配置以支持正确的MIME类型和CORS设置。
根据用户的问题,我们需要配置Nginx来正确提供TTF字体文件,包括:
- 设置正确的MIME类型(Content-Type)为 `font/ttf` 或 `application/font-sfnt`(注意:标准MIME类型为 `font/ttf`,但一些旧版本可能使用 `application/x-font-ttf`,不过最新的IANA注册的是 `font/ttf`)。
- 设置CORS(跨域资源共享)响应头,因为字体文件可能来自不同的域,而小程序可能需要跨域请求。
- 支持字节范围请求(Range Requests),因为字体文件通常较大,部分请求可以提高性能。
此外,我们还需要考虑Nginx的配置位置,通常是在服务器块(server block)中,针对字体文件的请求进行配置。
参考引用[1]中提到了Nginx的gzip配置,但用户的问题与gzip无关,而是关于字体文件的MIME类型和CORS。不过,我们也可以考虑在Nginx配置中开启gzip压缩字体文件(但要注意,有些浏览器对压缩的字体文件支持可能有问题,但现代浏览器一般没问题)。
步骤:
1. **设置MIME类型**:确保Nginx能够识别.ttf文件并返回正确的Content-Type。Nginx默认的mime.types文件通常包含字体类型的映射,但如果没有,我们需要手动添加。
2. **设置CORS**:在响应头中添加`Access-Control-Allow-Origin`,允许特定的域(或所有域`*`)访问字体资源。注意:小程序要求跨域请求,所以必须设置。
3. **支持字节范围请求**:通过设置`Accept-Ranges`和正确处理范围请求,Nginx默认支持,但需要确保。
4. **其他优化**:如缓存控制、gzip压缩等。
下面是一个Nginx配置示例,我们可以在server块中添加一个location来处理字体文件:
```nginx
server {
listen 80;
server_name your_domain.com;
# 其他配置...
# 针对字体文件的location
location ~ \.(ttf|ttc|otf|eot|woff|woff2)$ {
# 设置正确的MIME类型
types {
font/ttf ttf;
font/opentype otf;
application/font-woff woff;
application/font-woff2 woff2;
application/vnd.ms-fontobject eot;
}
# 或者使用下面一行简化的方式(如果mime.types已包含,则无需重复,但为了确保,可以显式设置)
add_header Content-Type font/ttf;
# 启用CORS
add_header 'Access-Control-Allow-Origin' '*';
# 如果需要指定域名,可以这样(注意:不能同时使用多个,可以用变量控制)
# add_header 'Access-Control-Allow-Origin' 'https://your_domain.com';
# 允许所有请求方法(对于字体,通常GET即可,但根据需求)
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
# 允许的请求头
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
# 处理预检请求的有效期
add_header 'Access-Control-Max-Age' 1728000;
# 返回类型为text/plain的预检请求响应
add_header 'Content-Type' 'text/plain; charset=utf-8' if ($request_method = 'OPTIONS');
# 预检请求直接返回204
if ($request_method = 'OPTIONS') {
return 204;
}
# 启用字节范围请求(Nginx默认支持,但可以显式设置)
add_header Accept-Ranges bytes;
# 设置缓存(可选)
expires max;
add_header Cache-Control "public, immutable";
# 启用gzip(可选,但注意字体文件可能已经是压缩过的,再次压缩效果不大)
# gzip on;
# gzip_types font/ttf;
}
}
```
注意:
- 上面的配置中,我们使用了通配符`*`来允许所有域名的跨域请求,这在开发阶段可能方便,但在生产环境中建议替换为具体的域名,以增加安全性。
- 对于MIME类型,我们显式设置了`Content-Type`为`font/ttf`,但要注意,如果Nginx的mime.types文件中已经包含了这些扩展名的映射,那么就不需要再设置。但为了确保,我们可以检查一下Nginx的默认mime.types文件(通常在`/etc/nginx/mime.types`),如果没有,则按上面的方式添加。
- 字节范围请求:Nginx默认支持,所以我们只需要在响应头中返回`Accept-Ranges: bytes`即可。
- 缓存设置:通过`expires`和`Cache-Control`头,可以让浏览器长时间缓存字体文件,减少重复请求。
另外,关于安卓小程序加载TTF字体失败,除了服务器配置,还需要检查:
- 字体文件的路径是否正确。
- 小程序端是否正确请求了字体文件(可以通过开发者工具查看网络请求)。
- 字体文件是否完整。
最后,配置完成后,重新加载Nginx配置:`nginx -s reload`。
测试方法:
1. 使用curl命令检查响应头:
```bash
curl -I http://your_domain.com/path/to/font.ttf
```
检查Content-Type、Access-Control-Allow-Origin等头是否存在且正确。
2. 在浏览器中打开开发者工具,查看字体请求的响应头。
3. 使用跨域请求测试工具。
相关问题:
1. 如何验证Nginx的配置是否正确?
2. 除了TTF字体,Nginx如何配置其他字体格式(如WOFF、WOFF2)?
3. 如何针对不同的字体类型设置不同的MIME类型?
4. 如何优化字体文件的传输(例如使用gzip压缩)?
5. 在Nginx中如何设置条件性的CORS(例如只允许特定域名)?</think>### 安卓小程序加载TTF字体失败及Nginx配置优化方案
#### 一、问题分析与解决方案
安卓小程序加载TTF字体失败通常由以下原因导致:
1. **MIME类型错误**
Nginx未正确识别`.ttf`文件的MIME类型,导致返回错误的`Content-Type`
2. **CORS限制**
字体请求被浏览器跨域策略拦截[^1]
3. **字节范围请求支持缺失**
字体文件需支持`Range`请求(部分内容请求)
#### 二、Nginx完整配置方案
在`nginx.conf`的`http`或`server`块中添加以下配置:
```nginx
# 1. 添加字体MIME类型映射
types {
font/ttf ttf;
font/opentype otf;
application/font-woff woff;
application/font-woff2 woff2;
application/vnd.ms-fontobject eot;
}
# 2. 字体文件专属配置
location ~* \.(ttf|otf|woff|woff2|eot)$ {
# 强制正确MIME类型
add_header Content-Type font/ttf;
# CORS配置(按需替换域名)
add_header 'Access-Control-Allow-Origin' 'https://your-miniapp-domain.com';
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,Range';
# 字节范围请求支持
add_header Accept-Ranges bytes;
# 缓存优化(1年)
expires 1y;
add_header Cache-Control "public, immutable";
# 启用gzip压缩(可选)
gzip on;
gzip_types font/ttf;
}
```
#### 三、关键配置说明
1. **MIME类型修复**
- 显式声明`font/ttf`类型覆盖默认配置
- 通过`types`块扩展Nginx支持的字体类型
2. **CORS核心配置**
```nginx
add_header 'Access-Control-Allow-Origin' 'https://your-miniapp-domain.com';
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS';
```
**注意**:将域名替换为实际小程序域名,多域名需用变量动态配置
3. **字节范围请求支持**
```nginx
add_header Accept-Ranges bytes; # 声明支持范围请求
```
确保Nginx能正确处理`Range`请求头(默认已支持)
4. **性能优化项**
- `expires 1y` + `immutable`:长期缓存优化
- `gzip on`:压缩字体文件(TTF压缩率约50-70%)[^1]
#### 四、验证步骤
1. **检查响应头**
```bash
curl -I https://your-server/font.ttf
```
确认包含:
```
Content-Type: font/ttf
Access-Control-Allow-Origin: https://your-miniapp-domain.com
Accept-Ranges: bytes
```
2. **跨域测试**
在浏览器控制台执行:
```javascript
fetch('https://your-server/font.ttf')
.then(res => console.log(res.headers.get('content-type')))
```
3. **安卓真机调试**
使用微信开发者工具的真机调试功能检测网络请求
#### 五、常见问题排查
1. **缓存问题**
修改配置后执行 `nginx -s reload` 并清除CDN/浏览器缓存
2. **路径匹配错误**
检查`location`正则是否匹配字体文件路径
3. **权限问题**
确保Nginx进程有字体文件的读取权限
4. **HTTPS证书**
小程序必须使用HTTPS,检查证书有效性
> 配置参考:Nginx官方MIME类型文档 [^2],HTTP访问控制规范 [^1]
阅读全文
相关推荐














