我正在尝试通过向我的Node / Express服务器发出请求,将音频文件从S3传输到我的React客户端。我设法实现了一些有效的方法,但我不确定我是否实际上流式传输文件,或者只是下载它。我怀疑我可能正在下载该文件,因为我对服务器的请求需要很长时间才能回来:
// assuming this file is Container.js
export default withRouter(Container)
// index.js
import Container from './Container'
render(
<BrowserRouter>
<Container/>
</BrowserRouter>,
document.getElementById('root')
)
请注意636.249毫秒!
你能告诉我这里做错了吗?我粘贴了下面我当前方法的代码;它执行以下操作:
Established database connection.
Server listening on port 9000!
::1 - - [18/Apr/2017:21:13:43 +0000] "GET / HTTP/1.1" 200 424 6.933 ms
::1 - - [18/Apr/2017:21:13:43 +0000] "GET /static/js/main.700ba5c4.js HTTP/1.1" 200 217574 1.730 ms
::1 - - [18/Apr/2017:21:13:43 +0000] "GET /index.css HTTP/1.1" 200 - 8.722 ms
Server received a request: GET /tracks
::1 - - [18/Apr/2017:21:13:43 +0000] "GET /tracks HTTP/1.1" 304 - 41.468 ms
Server received a request: GET /tracks/1/stream
::1 - - [18/Apr/2017:21:14:13 +0000] "GET /tracks/1/stream HTTP/1.1" 200 - 636.249 ms
Server received a request: GET /tracks/2/stream
Database query threw an error: ETIMEDOUT
/tracks/id/stream
(来自s3 package)获取文件服务器端:
downloadStream
客户端提取呼叫:
app.get('/tracks/:id/stream', (req, res) => {
const id = req.params.id
// Query the database for all tracks
database.query(`SELECT * FROM Tracks WHERE id = ${id}`, (error, results, fields) => {
// Upon failure...
if (error) {
res.sendStatus(500)
}
// Upon success...
const params = {
Bucket: bucketName, // use bucketName defined elsewhere
Key: results[0].key // use the key from the track object
};
// Download stream and pipe to client
const stream = client.downloadStream(params)
stream.pipe(res)
})
});
客户端AudioPlayer,负责处理实际的AudioBufferSourceNode:
const URL = `/tracks/${id}/stream`
const options = { method: 'GET' }
fetch(URL, options)
.then(response => response.arrayBuffer())
.then(data => {
// do some stuff
AudioPlayer.play(data)
})
答案 0 :(得分:2)
这里有很多错误,所以让我们一块一块地完成它,无论它是否与你原来的问题有关。
database.query(`SELECT * FROM Tracks WHERE id = ${id}`, (error, results, fields) => {
在这一行中,您将自己打开SQL注入攻击。 从不将任意数据连接到查询(或任何其他上下文)的上下文中,而不进行适当的转义。无论您使用何种数据库,都应该使用参数化方法。
我怀疑我可能正在下载该文件,因为我对服务器的请求需要很长时间才能回来
谁知道......您没有向我们展示您正在进行日志记录的单一位置,因此很难说明记录的行是否在请求之前或之后完成。然而,有一点很清楚,响应必须至少开始,否则响应状态代码将不会被知道。无论如何,来自S3的第一个资源字节的600 ms响应时间是闻所未闻的。
- 服务器使用downloadStream(来自s3包)获取文件
- 服务器将数据传输到客户端
醇>
你因此浪费了大量的带宽。您应该做的是签署一个15分钟到期的临时URL,然后将客户端重定向到该文件,而不是获取文件并将其中继到客户端。客户端将遵循重定向,现在S3负责处理您的客户。这将花费您一半的带宽,更少的CPU资源,并将从可能更接近您的用户的位置交付。您可以使用AWS JS SDK创建此签名URL。
- 客户端以ArrayBuffer
的形式接收数据 醇>
这里没有流媒体发生。您的客户正在下载整个资源,然后再播放任何内容。
应该做的是创建一个普通的音频实例。它会自动跟踪您从Node.js应用程序到已签名的S3 URL的重定向,并为您处理所有缓冲和流式传输。
let a = new Audio('/tracks/' + encodeURIComponent(id) + '/stream');
a.play();