ASP. NET core breakpoint continued to pass
In the ASP. NET Webapi wrote a complete breakpoint continuation of the article, at present, I only to the ASP. NET core will only be used, for the principle has not yet gone into deep learning, because of the park friends want to see the breakpoint continued in the implementation of ASP. It took a little time for this article to look at the rest of the home to see if ASP. NET core supports the continuation of breakpoints and the implementation of support and related APIs.
Breakpoint Continuation Basics
Previously in the ASP. NET Webapi for some of the basic content has been explained in detail, but also encapsulated, so the processing of ASP. NET core is just a different API use, The continuation of the breakpoint is focused on Acceptrange and contentrange and corresponding response request header settings, and the remaining and ASP. NET WEBAPI use indistinguishable.
In ASP. Webapi We encapsulate the operation interface Ifileprovider and the implementation fileprovider of the file, we are directly instantiated in the controller, we have the dependency injection in ASP. We can inject interfaces directly with the controller constructor.
public void ConfigureServices(IServiceCollection services){ services.AddMvc(); services.AddScoped<IFileProvider, FileProvider>();}
Of course, if you create a new ASP. NET Core Web application, then we create a new Downloadcontroller controller. In ASP. WEBAPI, the request-response mechanism object is httprequestmessage and Httpresponsemessage, while the ASP. NET core is the HttpRequest and HttpResponse objects. So how do we get these two objects in the controller? If we have a little bit of experience, we can understand that the request and response objects are necessarily stored in context, then how do we get the context? Obtained through the Ihttpcontextaccessor interface. So get the file interface and context in the Controller constructor and the corresponding constants as follows:
PrivateConstint buffersize =80 * 1024; Private const string MimeType = " Application/octet-stream "; public ifileprovider _fileprovider {get; set; }private ihttpcontextaccessor _contextaccessor; private HttpContext _context {get { return _contextaccessor.httpcontext;} }public FileDownloadController ( Ifileprovider Fileprovider, Ihttpcontextaccessor contextaccessor) {_fileprovider = Fileprovider; _contextaccessor = contextaccessor;}
Obtaining the request header range in ASP. WEBAPI takes advantage of the headers property in the request, but in ASP. NET core it needs to be obtained through the Gettypedheaders () method in the request.
ASP. NET core is more friendly for getting and setting parameters in the request header, for example we want to get the request type in the request header, in ASP. Webapi We specify the string request.headers["Content-type"], In the case of ASP. Request.headers[headernames.contenttype], which is specified directly by enumeration, it is much more convenient. Finally, the entire logic for the continuation of the ASP. NET core interrupts in the Downloadcontroller controller is as follows:
PublicClassfiledownloadcontroller{PrivateConstint buffersize =80 *1024;PrivateConstString MimeType ="Application/octet-stream";Public Ifileprovider _fileprovider {GetSet }Private Ihttpcontextaccessor _contextaccessor;Private HttpContext _context {get {return _contextaccessor.httpcontext; } }PublicFiledownloadcontroller (Ifileprovider Fileprovider, Ihttpcontextaccessor contextaccessor) {_fileprovider = Fileprovider; _contextAccessor = Contextaccessor; }///<summary>Download file///</summary>///<param name= "FileName" ></param>///<returns></returns> [HttpGet ("Api/download")]Public IactionresultGetFile (string filename) {filename ="Cn_windows_8_1_x64_dvd_2707237.iso";if (!_fileprovider.exists (FileName)) {ReturnNew Statuscoderesult (Statuscodes.status404notfound); }Get download file lengthvar filelength = _fileprovider.getlength (fileName);Initializing download file informationvar fileInfo = Getfileinfofromrequest (_context. Request, filelength);Get the remaining portion of the file streamvar stream =New Partialcontentfilestream (_fileprovider.open (fileName), Fileinfo.from, fileinfo.to);Sets the response request header Setresponseheaders (_context. Response, FileInfo, Filelength, fileName);ReturnNew Filestreamresult (Stream,New Mediatypeheadervalue (MimeType)); }///<summary>To give the encapsulated file information class based on the requested information///</summary>///<param name= "Request" ></param>///<param name= "Entitylength" ></param>///<returns></returns>Private FileInfoGetfileinfofromrequest (HttpRequest request,Long Entitylength) {var fileInfo =New FileInfo {from =0, to = entitylength-1, ispartial =False, Length = Entitylength};var requestheaders = Request. Gettypedheaders ();if (requestheaders.range! =Null && requestHeaders.Range.Ranges.Count >0) {var range = RequestHeaders.Range.Ranges.FirstOrDefault ();if (range. From.hasvalue && Range. From <0 | | Range. To.hasvalue && Range. To > Entitylength-1) {ReturnNull }var start = range. from;var end = range. to;if (start. HasValue) {if (start. Value >= entitylength) {ReturnNull }if (!end. HasValue | | End. Value >= entitylength) {end = Entitylength-1; } }else {if (end. Value = =0) {ReturnNull }var bytes = Math.min (end. Value, entitylength); start = Entitylength-bytes; End = start + Bytes-1; } fileinfo.ispartial =True Fileinfo.length = end. Value-start. Value +1; }return fileInfo; }///<summary>Setting the response header information///</summary>///<param name= "Response" ></param>///<param name= "FileInfo" ></param>///<param name= "Filelength" ></param>///<param name= "FileName" ></param>PrivatevoidSetresponseheaders (HttpResponse response, FileInfo FileInfo,long filelength, string fileName) {response. Headers[headernames.acceptranges] = "bytes"; Response. StatusCode = fileinfo.ispartial? StatusCodes.Status206PartialContent:StatusCodes.Status200OK; var contentdisposition = New Contentdispositionheadervalue ("attachment"); Contentdisposition.sethttpfilename (FileName); Response. Headers[headernames.contentdisposition] = contentdisposition.tostring (); Response. Headers[headernames.contenttype] = MimeType; Response. Headers[headernames.contentlength] = fileInfo.Length.ToString (); if (fileinfo.ispartial) {response. Headers[headernames.contentrange] = new Contentrangeheadervalue (Fileinfo.from, Fileinfo.to, FileLength). ToString (); } }}
Summarize
In ASP. Fileresult, Filestreamresult, Filephsicalresult have supported the continuation of the breakpoint, if a small file directly download, if a little larger file can be used to continue to pass the breakpoint, If you need a custom stream for a very large file to download it is more efficient, for example, to get a video stream file. We are still taking the form of a custom stream to implement the breakpoint continuation, if there is doubt about the custom flow and interface in the package, please move to the top right corner of my github see ASP. NET WEBAPI implementation. Both the ASP. NET WEBAPI and ASP. NET core breakpoint continued to implement the core logic, for some details are not considered therein, I hope that you want to learn the extension of the breakpoint to help you, I wish you a happy reading, Happy New Year! Complete code, I'll upload it to github!.
NET Core Breakpoint Continuation