http - 如何在 Rust 中使用媒体文件正确格式化 HTTP 响应

标签 http rust

我正在遵循 Rust 书籍 ( https://doc.rust-lang.org/book/ch20-00-final-project-a-web-server.html) 中的多线程 Web 服务器示例。

发送文本文件 (html) 效果很好。 Buy 尝试发送二进制 (mp3) 文件会在浏览器上出错。

要发送 MP3 文件,我正在尝试使用以下代码。 我认为问题出在内容的 String 转换上。 我试过更改标题,尝试另一种 Content-Type 什么都不买似乎有效。

let sent_bytes = contents.len();
let contents = &String::from_utf8_lossy(&contents[..]);
let response = format!("HTTP/1.0 200 OK\r\nContent-Type: audio/mpeg\r\nContent-Length: {}\r\n\r\n{}",
            sent_bytes,
            contents
        );
writer.write_all(response.as_bytes()).unwrap();
eprintln!("sent {}bytes\n", sent_bytes);
writer.flush().unwrap();

结果是浏览器无法重现该文件。事实上,如果我设法下载已发送的文件,它已损坏。

我应该如何编码文件以将其发送到浏览器?

最佳答案

您的问题是您假设二进制数据使用 UTF-8 编码,这是一个错误的假设。字节不是字符串,二进制数据不是 UTF-8。例如,MP3 将具有内部空字符值,这在 UTF-8 中是无效的。同样,某些字节模式是无效的(特别是无效的开始/继续字节模式),并且将被 Rust 删除,试图将 MP3 数据表示为 UTF-8 字符串。

比如说:

const MP3: &[u8] = b"ID3\x03\x00\x00\x00\x00\x00fTCON\x00\x00\x00\n\x00\x00\x00CinematicTALB\x00\x00\x00\x16\x00\x00\x00YouTube A";

如果我们尝试将其转换为 UTF-8,我们应该得到一个错误。如果我们使用 from_utf8_Lossy,它将根据 documentation 将任何无效的 UTF-8 数据转换为 U+FFFD .

Strings are made of bytes (u8), and a slice of bytes (&[u8]) is made of bytes, so this function converts between the two. Not all byte slices are valid strings, however: strings are required to be valid UTF-8. During this conversion, from_utf8_lossy() will replace any invalid UTF-8 sequences with U+FFFD REPLACEMENT CHARACTER, which looks like this: �

您要做的是将 HTML header 格式化为 UTF-8,将其转换为原始字节,然后在其后附加原始 MP3 数据。以下代码将为您执行此操作:

let contents = &MP3[..];
let response = format!("HTTP/1.0 200 OK\r\nContent-Type: audio/mpeg\r\nContent-Length: {}\r\n\r\n",
    contents.len(),
);
writer.write_all(response.as_bytes()).unwrap();
writer.write_all(contents).unwrap();
writer.flush().unwrap();

关于http - 如何在 Rust 中使用媒体文件正确格式化 HTTP 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57628633/

相关文章:

html - 动态内容的 css 文件中的数据 URI

HTTP:很少更改的图像的最佳 header 是什么

http - HTTP 302 重定向返回的位置不会出现在浏览器历史记录中?

rust - 我可以在嵌套类型上专门化特征吗?

reference - 如何抽象出对值或值本身的引用?

rest - 如何使用 Postman 对 Django REST Framework 进行身份验证

java - Android 中的 HTTPURL 连接速度慢

rust - 如何使用(不安全的)别名?

rust - 如何使 std::format 中的填充填充动态?

rust - Rust-调试和 Release模式的堆栈大小是否不同?