zoukankan      html  css  js  c++  java
  • MediaAPIController

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Net.Mime;
    using System.Web.Configuration;
    using System.Web.Http;
    namespace Fw.WebAPI.Controllers.FileAPI
    {
        [RoutePrefix("api/file/media")]
        public class MediaAPIController : ApiController
        {
            #region Fields
    
            // This will be used in copying input stream to output stream.
            public const int ReadStreamBufferSize = 1024 * 1024;
            // We have a read-only dictionary for mapping file extensions and MIME names. 
            public static readonly IReadOnlyDictionary<string, string> MimeNames;
            // We will discuss this later.
            public static readonly IReadOnlyCollection<char> InvalidFileNameChars;
            // Where are your videos located at? Change the value to any folder you want.
            public static readonly string InitialDirectory;
    
            #endregion
    
            #region Constructors
    
            static MediaAPIController()
            {
                var mimeNames = new Dictionary<string, string>();
    
                mimeNames.Add(".mp3", "audio/mpeg");    // List all supported media types; 
                mimeNames.Add(".mp4", "video/mp4");
                mimeNames.Add(".ogg", "application/ogg");
                mimeNames.Add(".ogv", "video/ogg");
                mimeNames.Add(".oga", "audio/ogg");
                mimeNames.Add(".wav", "audio/x-wav");
                mimeNames.Add(".webm", "video/webm");
    
                MimeNames = new ReadOnlyDictionary<string, string>(mimeNames);
    
                InvalidFileNameChars = Array.AsReadOnly(Path.GetInvalidFileNameChars());
                InitialDirectory = WebConfigurationManager.AppSettings["InitialDirectory"];
            }
    
            #endregion
    
            #region Actions
            [Route("Play/{id}")]
            [HttpGet]
            public HttpResponseMessage Play(string id)
            {
                //从Gridfs中取文件流
                IDFSHandle dsfHandle = new GridFSHandle();
                Stream stream=dsfHandle.GetFile(id);
    
                // This can prevent some unnecessary accesses. 
                // These kind of file names won't be existing at all. 
                if (stream==null)
                    throw new HttpResponseException(HttpStatusCode.NotFound);
    
    
                long totalLength = stream.Length;
    
                RangeHeaderValue rangeHeader = base.Request.Headers.Range;
                HttpResponseMessage response = new HttpResponseMessage();
    
                response.Headers.AcceptRanges.Add("bytes");
    
                // The request will be treated as normal request if there is no Range header.
                if (rangeHeader == null || !rangeHeader.Ranges.Any())
                {
                    response.StatusCode = HttpStatusCode.OK;
                    response.Content = new PushStreamContent((outputStream, httpContent, transpContext)
                    =>
                    {
                        using (outputStream) // Copy the file to output stream straightforward. 
                      
                            try
                            {
                                stream.CopyTo(outputStream, ReadStreamBufferSize);
                            }
                            catch (Exception error)
                            {
                                Debug.WriteLine(error);
                            }
                        
                    }, GetMimeNameFromExt("mp4"));
    
                    response.Content.Headers.ContentLength = totalLength;
                    return response;
                }
    
                long start = 0, end = 0;
    
                // 1. If the unit is not 'bytes'.
                // 2. If there are multiple ranges in header value.
                // 3. If start or end position is greater than file length.
                if (rangeHeader.Unit != "bytes" || rangeHeader.Ranges.Count > 1 ||
                    !TryReadRangeItem(rangeHeader.Ranges.First(), totalLength, out start, out end))
                {
                    response.StatusCode = HttpStatusCode.RequestedRangeNotSatisfiable;
                    response.Content = new StreamContent(Stream.Null);  // No content for this status.
                    response.Content.Headers.ContentRange = new ContentRangeHeaderValue(totalLength);
                    response.Content.Headers.ContentType = GetMimeNameFromExt("mp4");
    
                    return response;
                }
    
                var contentRange = new ContentRangeHeaderValue(start, end, totalLength);
    
                // We are now ready to produce partial content.
                response.StatusCode = HttpStatusCode.PartialContent;
                response.Content = new PushStreamContent((outputStream, httpContent, transpContext)
                =>
                {
                    using (outputStream) // Copy the file to output stream in indicated range.
                    
                    CreatePartialContent(stream, outputStream, start, end);
    
                }, GetMimeNameFromExt("mp4"));
    
                response.Content.Headers.ContentLength = end - start + 1;
                response.Content.Headers.ContentRange = contentRange;
    
                return response;
            }
    
            #endregion
    
            #region Others
    
            private static bool AnyInvalidFileNameChars(string fileName)
            {
                return InvalidFileNameChars.Intersect(fileName).Any();
            }
    
            private static MediaTypeHeaderValue GetMimeNameFromExt(string ext)
            {
                string value;
    
                if (MimeNames.TryGetValue(ext.ToLowerInvariant(), out value))
                    return new MediaTypeHeaderValue(value);
                else
                    return new MediaTypeHeaderValue(MediaTypeNames.Application.Octet);
            }
    
            private static bool TryReadRangeItem(RangeItemHeaderValue range, long contentLength,
                out long start, out long end)
            {
                if (range.From != null)
                {
                    start = range.From.Value;
                    if (range.To != null)
                        end = range.To.Value;
                    else
                        end = contentLength - 1;
                }
                else
                {
                    end = contentLength - 1;
                    if (range.To != null)
                        start = contentLength - range.To.Value;
                    else
                        start = 0;
                }
                return (start < contentLength && end < contentLength);
            }
    
            private static void CreatePartialContent(Stream inputStream, Stream outputStream,
                long start, long end)
            {
                int count = 0;
                long remainingBytes = end - start + 1;
                long position = start;
                byte[] buffer = new byte[ReadStreamBufferSize];
                
                inputStream.Position = start;
                do
                {
                    try
                    {
                        if (remainingBytes > ReadStreamBufferSize)
                            count = inputStream.Read(buffer, 0, ReadStreamBufferSize);
                        else
                            count = inputStream.Read(buffer, 0, (int)remainingBytes); 
                        outputStream.Write(buffer, 0, count);
                    }
                    catch (Exception error)
                    {
                        Debug.WriteLine(error);
                        break;
                    }
                    position = inputStream.Position;
                    remainingBytes = end - position + 1;
                } while (position <= end);
            }
    
            #endregion
        }
    }
    

      

  • 相关阅读:
    0309. Best Time to Buy and Sell Stock with Cooldown (M)
    0621. Task Scheduler (M)
    0106. Construct Binary Tree from Inorder and Postorder Traversal (M)
    0258. Add Digits (E)
    0154. Find Minimum in Rotated Sorted Array II (H)
    0797. All Paths From Source to Target (M)
    0260. Single Number III (M)
    0072. Edit Distance (H)
    0103. Binary Tree Zigzag Level Order Traversal (M)
    0312. Burst Balloons (H)
  • 原文地址:https://www.cnblogs.com/YrRoom/p/11773711.html
Copyright © 2011-2022 走看看