Yêu cầu phạm vi và phản hồi một phần trong ASP.NET Core
Đã qua lâu rồi cái thời mà tốc độ internet là một vấn đề đối với hầu hết những người làm công nghệ. Tôi đã tải xuống một video để thử nghiệm cho bài viết này, tôi quên mất nơi đặt file video này và thay vì tìm kiếm trên máy cục bộ của mình, tôi đã quyết định tải xuống lại. Đó là một lợi ích của cuộc sống trong tương lai.
Mặc dù người tiêu dùng Internet có thể coi thường băng thông và truyền dữ liệu, nhưng các nhà phát triển có thể muốn xem xét việc tải xuống hoàn chỉnh lặp đi lặp lại sẽ ảnh hưởng gì đến chi tiêu ngân sách và trải nghiệm người dùng.
Trong bài viết này, chúng ta sẽ thấy ba cách để xử lý các yêu cầu phạm vi HTTP (HTTP range request), những lợi ích mà chúng ta sẽ thấy khi sử dụng chúng và cách chúng hoạt động trong trình duyệt web của chúng ta.
Bắt đầu nào.
Vấn đề tải xuống hoàn chỉnh
Sự phát triển của internet đã đưa chúng ta đến một thời điểm mà chúng ta thường truyền hàng gigabyte thông tin từ máy chủ đến máy khách. Các nền tảng như Netflix, HBO Max và TikTok sẽ truyền trực tuyến các tệp video như trải nghiệm cốt lõi của chúng.
Mặc dù hầu hết người tiêu dùng có thể xem video từ đầu đến cuối, nhưng vẫn xảy ra gián đoạn, phải tạm dừng hoặc bỏ dở phiên xem.
Làm thế nào để chúng ta tiếp tục một tệp từ một điểm cụ thể?
Chà, có một giải pháp trực tiếp cho vấn đề này trong đặc tả HTTP. Nó được gọi là yêu cầu phạm vi HTTP (HTTP range request).
Yêu cầu phạm vi HTTP là gì?
** Yêu cầu phạm vi HTTP (HTTP range request) cho phép máy khách yêu cầu máy chủ gửi một phần phản hồi đến máy khách. **
Các yêu cầu phạm vi HTTP một phần có lợi nhất khi được sử dụng với tải xuống tệp lớn và có thêm lợi ích là hỗ trợ chức năng tạm dừng và tiếp tục trên ứng dụng khách.
Để bắt đầu một yêu cầu phạm vi một phần, máy khách phải bắt đầu một yêu cầu đến máy chủ và có khả năng sẽ nhận được hai tiêu đề: Accept-Ranges
và Content-Length
.
Nếu máy chủ hỗ trợ các yêu cầu phạm vi một phần, giá trị cho Accept-Ranges
sẽ là bytes
; nếu không, giá trị sẽ là none
. Content-Length
là tổng kích thước tệp mà máy khách có thể mong đợi khi truy xuất tài nguyên.
HTTP/1.1 200 OK
...
Accept-Ranges: bytes
Content-Length: 100000
Trong một số trường hợp, máy chủ có thể hỗ trợ yêu cầu HEAD
, cho phép chúng ta chỉ nhận thông tin tiêu đề của tài nguyên mà không truyền toàn bộ tải trọng.
Giả sử máy chủ có thể xử lý các yêu cầu phạm vi một phần, bây giờ chúng ta có thể thêm tiêu đề Range
vào yêu cầu HTTP của mình với định dạng bytes=[start]-[end]
.
GET /puppies.mp4 HTTP/1.1
Host: localhost
Range: bytes=0-100
Khi thành công, chúng tôi sẽ nhận được mã trạng thái HTTP 206 Partial Content
cùng với các tiêu đề bổ sung của Content-Range
và Content-Length
.
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-100/100000
Content-Length: 100
...
(binary content)
Điều quan trọng cần lưu ý Content-Length
là độ dài của tải trọng phản hồi, không phải tổng kích thước tệp. Để truy xuất toàn bộ kích thước tệp, chúng ta có thể phân tích cú pháp tiêu đề Content-Range
và sử dụng giá trị sau /
.
Nói chung, chúng ta có thể mong đợi ba mã trạng thái phản hồi khác nhau từ một máy chủ:
206 Partial Content
: Máy chủ đã xử lý thành công một phần yêu cầu và gửi một phần trọng tải.416 Requested Range Not Satisfiable
: Đã xảy ra lỗi với một phần yêu cầu, có thể nằm ngoài giới hạn và phản hồi phản ánh sự thất bại.200 OK
: Không hỗ trợ các yêu cầu một phần và máy chủ đang trả lại toàn bộ tài nguyên.
Để đọc chi tiết đầy đủ hơn về yêu cầu phạm vi HTTP, tôi khuyên bạn nên đọc tài liệu Mozilla.
Tuyệt vời, vậy làm cách nào để chúng tôi sử dụng các yêu cầu và phản hồi từng phần với ASP.NET Core?
Triển khai yêu cầu phạm vi HTTP bằng middleware StaticFile
Cách đầu tiên và đơn giản nhất để sử dụng các yêu cầu phạm vi HTTP là để ASP.NET Core thực hiện tất cả công việc. Middleware StaticFileMiddleware
của ASP.NET Core hỗ trợ các phản hồi một phần. Thêm tệp vào thư mục wwwroot
của chúng ta sẽ tự động cho phép ASP.NET Core và máy chủ trả về các tệp đa phương tiện lớn hơn theo từng phần.
Trong lớp Startup
, chúng ta cần thêm đăng ký StaticFileMiddleware
trong phương thức Configure
của mình.
app.UseStaticFiles();
Trong thư mục wwwroot
, chúng ta sẽ lưu trữ một tệp video.mp4
, tệp này sẽ cho phép máy chủ gửi tệp đến máy khách.
Cuối cùng, trong trang Razor, chúng ta có thể thêm một thẻ video
để truy xuất tệp video của chúng ta và hiển thị nó cho trình duyệt.
<div>
<h2>Static</h2>
<video
src="video.mp4"
width="400"
controls>
</video>
</div>
Hãy xem điều gì sẽ xảy ra trong các công cụ dành cho nhà phát triển trình duyệt web của chúng ta.
Như chúng ta có thể thấy, mã trạng thái 206 Partial Content
, cùng với các tiêu đề Accept-Ranges
và Content-Range
. Trong ví dụ cụ thể này, phạm vi byte nhỏ mà trọng tải trả về là video hoàn chỉnh.
Triển khai yêu cầu phạm vi HTTP trong ASP.NET Core MVC
Đôi khi chúng ta cần ẩn các tệp sau một lớp logic nghiệp vụ và middleware StaticFileMiddleware
có thể không phù hợp với vấn đề của chúng ta.
May mắn cho các nhà phát triển ASP.NET Core MVC, chức năng này được hiển thị thông qua FileStreamResult
được triển khai từ interface IActionResult
. Class FileStreamResult
có thể hỗ trợ xử lý yêu cầu phạm vi HTTP.
Trong ví dụ này, chúng ta sẽ sử dụng cùng một tệp video nhưng tạo một luồng có thể đọc được để chuyển làm tham số cho phương thức File
của controller.
public class VideoController : Controller
{
private readonly IWebHostEnvironment environment;
public VideoController(IWebHostEnvironment environment)
{
this.environment = environment;
}
// GET
[HttpGet, Route("videos/video.mp4")]
public IActionResult Index()
{
var video = environment
.WebRootFileProvider
.GetFileInfo("video.mp4")
.CreateReadStream();
return File(video, "video/mp4", enableRangeProcessing: true);
}
}
Chúng ta cũng sẽ nhận thấy chúng ta cần phải thiết lập các tham số tùy chọn của enableRangeProcessing
thành true
để có được những chức năng mong đợi.
Hãy cập nhật trang Razor để gọi phương thức hành động của controller.
<div>
<h2>Partial</h2>
<video
src="@Url.Action("Index", "Video")"
width="400" controls>
</video>
</div>
Hãy xem điều gì đang xảy ra trong các công cụ phát triển trình duyệt của chúng ta.
Tương tự như StaticFileMiddleware
, chúng ta sẽ thấy tất cả các dấu hiệu của một yêu cầu phạm vi HTTP và một phần phản hồi.
Chúng tôi có thêm lợi ích là hỗ trợ tất cả các luồng, không chỉ các luồng đọc từ đĩa cục bộ.
Phần kết luận
Yêu cầu phạm vi HTTP diễn ra rõ ràng đối với hầu hết người dùng trình duyệt, nhưng biết rằng phản hồi một phần có thể xảy ra sẽ mở ra một thế giới các tính năng tạm dừng / tiếp tục mới cho các nhà phát triển đang xây dựng ứng dụng khách.
May mắn thay, chúng ta có thể tiếp tục sử dụng ASP.NET Core làm proxy cho các tệp đa phương tiện lớn trong khi vẫn nhận được các lợi ích của tính năng đặc tả HTTP cụ thể này.
Nếu chúng ta cần một hành vi khác với ASP.NET Core, chúng ta có thể truy cập các giá trị của tiêu đề trực tiếp từ lớp HttpRequest
và tạo các phản hồi theo nhu cầu của chúng ta.
Điều quan trọng cần lưu ý là máy chủ lưu trữ cơ bản, IIS và Kestrel, phải có hỗ trợ cho tính năng này; nếu không, nó sẽ không hoạt động.
Như mọi khi, cảm ơn bạn vì đã đọc.