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

如何使用媒体文件在HTTP响应中正确格式化,http,rust,Http,Rust,下面是Rust book()中的多线程web服务器示例 发送文本文件(html)非常有效。Buy尝试发送二进制(mp3)文件时在浏览器上出现错误 要发送MP3文件,我正在尝试以下代码。 我认为问题在于内容的字符串转换。 我尝试过更改标题,尝试另一种内容类型buy nothing似乎有效 let sent_bytes = contents.len(); let contents = &String::from_utf8_lossy(&contents[..]); let respo

下面是Rust book()中的多线程web服务器示例

发送文本文件(html)非常有效。Buy尝试发送二进制(mp3)文件时在浏览器上出现错误

要发送MP3文件,我正在尝试以下代码。 我认为问题在于内容的字符串转换。 我尝试过更改标题,尝试另一种内容类型buy nothing似乎有效

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中无效。同样,某些字节模式是无效的(特别是无效的开始/继续字节模式),并且将通过尝试将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,我们将得到一个错误。如果我们使用来自\U utf8\U Lossy的
,它将根据

字符串由字节(u8)组成,字节片(&[u8])由字节组成,因此此函数在两者之间进行转换。但并非所有字节片都是有效字符串:字符串必须是有效的UTF-8。在此转换过程中,from_utf8_lossy()将用U+FFFD替换字符替换任何无效的UTF-8序列,如下所示:�

您要做的是将HTML头格式化为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();

您假设内容是有效的UTF8,这对于二进制文件(MP3)来说不是一个好的假设。尝试打印
内容
,您应该什么都没有。显然,它可以很好地处理内部空字符,但很可能是没有起始字节的连续字节或相反的字节会损坏它。不要假设二进制数据是UTF8。