node.js - 如何提供具有字节范围的播客(用于 iTunes 连接)
问题描述
我为 NodeJS 服务器添加了代码以提供播客剧集。我没有对字节范围请求进行编程,iTunes Connect 也没有对其进行验证。我使用包构建了 XML 文件rss
,尽管我可以手动编写它。相关代码为:
/**
* GET /podcast/:dayId
*
* Serve podcast episodes.
*/
router.get('/podcast/:dayId', async (req, res) => {
let dayIdStr = req.params.dayId;
let filepath = path.join(__dirname, "../podcast/" + dayIdStr + ".mp3");
if (!fs.existsSync(filepath)) {
console.log("Error in serving podcast episode " + dayIdStr);
res.redirect("/404");
}
res.sendFile(filepath);
});
/**
*
* GET /podcast
*
* Serve RSS feed to podcast
*/
router.get('/podcast', async (req, res) => {
let filepath = path.join(__dirname, `../podcast/podcast.xml`)
//res.contentType('application/xml');
res.sendFile(filepath);
});
我知道我需要添加一个 header Accept-Ranges: bytes
,将响应 header 设置为206 Partial Response
,并发送 header 请求的字节。相关线程iTunes Range 请求;播客被拒绝只回答第二个。express-range包仅包含 JSON 对象的文档。
如何在 NodeJS 中编写这三个条件?
解决方案
来自 Express 的本机支持
ExpresssendFile
支持开箱即用的字节范围请求(如send
评论中所述)。您只需要添加 206 状态码:
res.status(206);
res.sendFile(filepath);
调试
要调试您的服务器是否正常工作,请执行以下步骤:
- 通过请求 20 个字节来验证服务器是否支持字节范围请求;如果结果是 21,那么你得到了正确的字节数(取自ServerFault):
$ curl --silent --range 20-40 https://emotionathletes.org/podcast/1.mp3 | wc -c
21
- 请求整个文件时测试头部的响应代码:
$ curl --head https://emotionathletes.org/podcast/1.mp3
HTTP/1.1 206 Partial Content
X-Powered-By: Express
Accept-Ranges: bytes
...
- 请求范围时测试响应代码和字节范围(这个可能是多余的)
$ curl -H Range:bytes=20-40 -I https://emotionathletes.org/podcast/1.mp3
HTTP/1.1 206 Partial Content
X-Powered-By: Express
Accept-Ranges: bytes
...
您也可以使用wget
而不是进行测试curl
,例如:
wget --header="Range: bytes=20-40" -t 1 https://emotionathletes.org/podcast/1.mp3
您可以wget
使用macOS
.brew
仍然失败?检查 XML 提要
如果这一切正常,但您仍然在 iTunes 连接上遇到验证失败,则问题可能出在 XML 提要上。考虑复制适用于 iTunes 连接(例如我的)的 XML 提要的结构,或寻求具体帮助。
就我而言,我正在提供 podcast 标识,/podcast/1
而 iTunes 甚至没有尝试下载它们,因为它们缺少扩展名。iTunes 通过用户代理iTMS
和请求提要Jakarta
,但没有请求剧集。与成功的提要相比,我意识到我需要一个扩展,所以我使用了它。
在 NodeJS 中构建 XML 提要
您还可以使用该rss
包从 NodeJS 构建 RSS 提要。属性有点棘手,例如iTunes 需要一个带有 url 的附件,所以我podcast.js
在这里复制我的部分。为简单起见,我将其编译为带有 的静态 XML 文件node podcast.js
,然后像任何其他静态文件一样提供服务。
const fs = require('fs');
const path = require('path');
const RSS = require('rss');
/* lets create an rss feed */
var feed = new RSS({
itunesExplicit: false,
title: 'Ginja',
description: 'Um curso virtual que desenvolve a inteligência emocional nas crianças',
feed_url: 'https://emocoes.org/podcast-feed',
site_url: 'https://emocoes.org',
image_url: 'http://emocoes.org/images/logo_podcast.png',
managingEditor: 'Miguel Morin',
webMaster: 'Miguel Morin',
copyright: '2020 Atletismo Emocional',
language: 'pt',
categories: ['Education for Kids','Stories for Kids','Mental Health'],
pubDate: 'October 20, 2020 22:00:00 GMT',
ttl: '60',
custom_namespaces: {
'itunes': 'http://www.itunes.com/dtds/podcast-1.0.dtd'
},
custom_elements: [
{'itunes:explicit': 'no'},
{'itunes:subtitle': 'Atletismo Emocional para crianças'},
{'itunes:author': 'Ginja'},
{'itunes:summary': 'Olá crianças! Eu sou o Ginja, o guru das emoções! Ao longo de várias aventuras com os meus amigos, vamos aprender a reconhecer, aceitar e utilizar as nossas emoções. E no fim, vamos ser uns atletas emocionais e chegar à meta da felicidade.\n\nVisitem a minha página: https://emocoes.org\n\nSigam-me no Facebook: https://facebook.com/emotionathletes\n\nSigam-me no Instagram: https://instagram.com/emotionathletes\n\nSigam-me no Twitter: https://twitter.com/emotionathletes'},
{'itunes:owner': [
{'itunes:name': 'Ginja'},
{'itunes:email': 'ginja@emocoes.org'}
]},
{'itunes:image': {
_attr: {
href: 'http://emocoes.org/images/logo_podcast.png'
}
}},
{'itunes:category': [
{_attr: {
text: 'Kids & Family'
}},
{'itunes:category': {
_attr: {
text: 'Education for Kids'
}
}}
]}
]
});
/* loop over data and add to feed */
feed.item({
title: '1: Bem-vindos!',
description: 'O Ginja explica que as emoções são como as ondas do mar. (Mensagem principal: As emoções são como as ondas do mar: vêm e vão, não as podemos parar.)',
url: 'https://emocoes.org/podcast/1.mp3', // link to the item
date: 'October 20, 2020 22:00:00 GMT', // any format that js Date can parse.
custom_elements: [
{'itunes:author': 'Ginja'},
{'itunes:subtitle': 'O Ginja explica que as emoções são como as ondas do mar. (Mensagem principal: As emoções são como as ondas do mar: vêm e vão, não as podemos parar.)'},
{'itunes:duration': '4:23'},
{'enclosure url="https://emocoes.org/podcast/1.mp3" length="8520238" type="audio/mpeg"': {}}
]
});
var xml = feed.xml({indent: true});
let filepath = path.join(__dirname, `./public/podcast.xml`)
fs.writeFile(filepath, xml, (err) => {if (err) throw err;});
其他选项
nginx
作为播客服务器提到的评论。我找不到如何做到这一点,并在ServerFault上询问了它。
推荐阅读
- mysql - 如何在高流量应用程序中将写入查询从 MySQL 迁移到 Redis?
- node.js - Nest.js WebSocket 返回传输未知
- paypal - 无法在 ionic 3 项目中登录贝宝
- node.js - MongoDB .find NodeJS 的问题
- javascript - 已获取电子邮件信息但需要附件名称的 Google 脚本
- php - 如何获取laravel项目中所有具有属性的表的名称
- php - JQUERY在文本函数上自动完成,该函数从html表单中的其他文本中获取输入
- google-api - 日历未与课堂链接
- ios - 我应该永远将 WKWebView 保留在 UICollectionView 中以避免重新加载吗?
- javascript - 是否可以在 Ajax 调用之前读取 Microsoft Excel 文件的内容?