Skip to content

Commit

Permalink
You can now download files from the media server for offline watching
Browse files Browse the repository at this point in the history
  • Loading branch information
Zexuz committed Apr 21, 2019
1 parent 72e3763 commit 755588b
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 34 deletions.
48 changes: 38 additions & 10 deletions SnackTime.MediaServer.Proto/csharp/FileDownload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,19 @@ static FileDownloadReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"CiZwcm90by9maWxlLXNlcnZpY2UvZmlsZS1kb3dubG9hZC5wcm90bxIVc25h",
"Y2t0aW1lLnNlcmllcy5maWxlIhUKE0Rvd25sb2FkRmlsZVJlcXVlc3QisAEK",
"FFJlc3BvbnNlRG93bmxvYWRGaWxlEjEKB3N0YXJ0ZWQYASABKAsyHi5zbmFj",
"a3RpbWUuc2VyaWVzLmZpbGUuU3RhcnRlZEgAEjAKCHByb2dyZXNzGAIgASgL",
"Mhwuc25hY2t0aW1lLnNlcmllcy5maWxlLkNodW5rSAASKwoEZG9uZRgDIAEo",
"CzIbLnNuYWNrdGltZS5zZXJpZXMuZmlsZS5Eb25lSABCBgoEdHlwZSJBCgdT",
"dGFydGVkEg4KBmxlbmdodBgBIAEoARIUCgxzaXplUGVyQ2h1bmsYAiABKAUS",
"EAoIRmlsZU5hbWUYAyABKAkiGAoFQ2h1bmsSDwoHQ29udGVudBgBIAEoDCIU",
"CgREb25lEgwKBEhhc2gYASABKAlCJaoCIlNuYWNrVGltZS5NZWRpYVNlcnZl",
"ci5TZXJ2aWNlLkZpbGViBnByb3RvMw=="));
"Y2t0aW1lLnNlcmllcy5maWxlIioKE0Rvd25sb2FkRmlsZVJlcXVlc3QSEwoL",
"bWVkaWFGaWxlSWQYASABKAkisAEKFFJlc3BvbnNlRG93bmxvYWRGaWxlEjEK",
"B3N0YXJ0ZWQYASABKAsyHi5zbmFja3RpbWUuc2VyaWVzLmZpbGUuU3RhcnRl",
"ZEgAEjAKCHByb2dyZXNzGAIgASgLMhwuc25hY2t0aW1lLnNlcmllcy5maWxl",
"LkNodW5rSAASKwoEZG9uZRgDIAEoCzIbLnNuYWNrdGltZS5zZXJpZXMuZmls",
"ZS5Eb25lSABCBgoEdHlwZSJBCgdTdGFydGVkEg4KBmxlbmdodBgBIAEoARIU",
"CgxzaXplUGVyQ2h1bmsYAiABKAUSEAoIRmlsZU5hbWUYAyABKAkiGAoFQ2h1",
"bmsSDwoHQ29udGVudBgBIAEoDCIUCgREb25lEgwKBEhhc2gYASABKAlCJaoC",
"IlNuYWNrVGltZS5NZWRpYVNlcnZlci5TZXJ2aWNlLkZpbGViBnByb3RvMw=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::SnackTime.MediaServer.Service.File.DownloadFileRequest), global::SnackTime.MediaServer.Service.File.DownloadFileRequest.Parser, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::SnackTime.MediaServer.Service.File.DownloadFileRequest), global::SnackTime.MediaServer.Service.File.DownloadFileRequest.Parser, new[]{ "MediaFileId" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::SnackTime.MediaServer.Service.File.ResponseDownloadFile), global::SnackTime.MediaServer.Service.File.ResponseDownloadFile.Parser, new[]{ "Started", "Progress", "Done" }, new[]{ "Type" }, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::SnackTime.MediaServer.Service.File.Started), global::SnackTime.MediaServer.Service.File.Started.Parser, new[]{ "Lenght", "SizePerChunk", "FileName" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::SnackTime.MediaServer.Service.File.Chunk), global::SnackTime.MediaServer.Service.File.Chunk.Parser, new[]{ "Content" }, null, null, null),
Expand Down Expand Up @@ -73,6 +73,7 @@ public DownloadFileRequest() {

[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public DownloadFileRequest(DownloadFileRequest other) : this() {
mediaFileId_ = other.mediaFileId_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}

Expand All @@ -81,6 +82,17 @@ public DownloadFileRequest Clone() {
return new DownloadFileRequest(this);
}

/// <summary>Field number for the "mediaFileId" field.</summary>
public const int MediaFileIdFieldNumber = 1;
private string mediaFileId_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string MediaFileId {
get { return mediaFileId_; }
set {
mediaFileId_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}

[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as DownloadFileRequest);
Expand All @@ -94,12 +106,14 @@ public bool Equals(DownloadFileRequest other) {
if (ReferenceEquals(other, this)) {
return true;
}
if (MediaFileId != other.MediaFileId) return false;
return Equals(_unknownFields, other._unknownFields);
}

[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override int GetHashCode() {
int hash = 1;
if (MediaFileId.Length != 0) hash ^= MediaFileId.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
Expand All @@ -113,6 +127,10 @@ public override string ToString() {

[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
if (MediaFileId.Length != 0) {
output.WriteRawTag(10);
output.WriteString(MediaFileId);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
Expand All @@ -121,6 +139,9 @@ public void WriteTo(pb::CodedOutputStream output) {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
if (MediaFileId.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(MediaFileId);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
Expand All @@ -132,6 +153,9 @@ public void MergeFrom(DownloadFileRequest other) {
if (other == null) {
return;
}
if (other.MediaFileId.Length != 0) {
MediaFileId = other.MediaFileId;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}

Expand All @@ -143,6 +167,10 @@ public void MergeFrom(pb::CodedInputStream input) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
MediaFileId = input.ReadString();
break;
}
}
}
}
Expand Down
43 changes: 36 additions & 7 deletions SnackTime.MediaServer.Proto/csharp/Storage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,20 @@ static StorageReflection() {
"ChNwcm90by9zdG9yYWdlLnByb3RvEhFzbmFja3RpbWUuc3RvcmFnZSJfCglN",
"ZWRpYUZpbGUSEAoIZmlsZU5hbWUYASABKAkSEQoJbWVkaWFOYW1lGAIgASgJ",
"EhUKDWRvd25sb2FkZWRVVEMYAyABKAkSFgoObGFzdFdhdGNoZWRVVEMYBCAB",
"KAkikQEKB1Nlc3Npb24SCgoCaWQYASABKAkSEAoIc3RhcnRVVEMYAiABKAMS",
"KAkipQEKB1Nlc3Npb24SCgoCaWQYASABKAkSEAoIc3RhcnRVVEMYAiABKAMS",
"DgoGZW5kVVRDGAMgASgDEg8KB21lZGlhSWQYBCABKAkSLQoIZHVyYXRpb24Y",
"BSABKAsyGy5zbmFja3RpbWUuc3RvcmFnZS5EdXJhdGlvbhIYChBtZWRpYUxl",
"bmdodEluU2VjGAYgASgBIj4KCER1cmF0aW9uEhkKEXN0YXJ0UG9zdGlvbklu",
"U2VjGAEgASgBEhcKD2VuZFBvc3Rpb25JblNlYxgCIAEoASJICghQcm9ncmVz",
"cxIUCgx3YXRjaGVkSW5TZWMYASABKAESDgoGbGVuZ2h0GAIgASgBEhYKDmxh",
"c3RXYXRjaGVkVXRjGAMgASgBQi+qAixTbmFja1RpbWUuTWVkaWFTZXJ2ZXIu",
"U3RvcmFnZS5Qcm90b0dlbmVyYXRlZGIGcHJvdG8z"));
"bmdodEluU2VjGAYgASgBEhIKCmZyb21EZXZpY2UYByABKAkiPgoIRHVyYXRp",
"b24SGQoRc3RhcnRQb3N0aW9uSW5TZWMYASABKAESFwoPZW5kUG9zdGlvbklu",
"U2VjGAIgASgBIkgKCFByb2dyZXNzEhQKDHdhdGNoZWRJblNlYxgBIAEoARIO",
"CgZsZW5naHQYAiABKAESFgoObGFzdFdhdGNoZWRVdGMYAyABKAFCL6oCLFNu",
"YWNrVGltZS5NZWRpYVNlcnZlci5TdG9yYWdlLlByb3RvR2VuZXJhdGVkYgZw",
"cm90bzM="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::SnackTime.MediaServer.Storage.ProtoGenerated.MediaFile), global::SnackTime.MediaServer.Storage.ProtoGenerated.MediaFile.Parser, new[]{ "FileName", "MediaName", "DownloadedUTC", "LastWatchedUTC" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::SnackTime.MediaServer.Storage.ProtoGenerated.Session), global::SnackTime.MediaServer.Storage.ProtoGenerated.Session.Parser, new[]{ "Id", "StartUTC", "EndUTC", "MediaId", "Duration", "MediaLenghtInSec" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::SnackTime.MediaServer.Storage.ProtoGenerated.Session), global::SnackTime.MediaServer.Storage.ProtoGenerated.Session.Parser, new[]{ "Id", "StartUTC", "EndUTC", "MediaId", "Duration", "MediaLenghtInSec", "FromDevice" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::SnackTime.MediaServer.Storage.ProtoGenerated.Duration), global::SnackTime.MediaServer.Storage.ProtoGenerated.Duration.Parser, new[]{ "StartPostionInSec", "EndPostionInSec" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::SnackTime.MediaServer.Storage.ProtoGenerated.Progress), global::SnackTime.MediaServer.Storage.ProtoGenerated.Progress.Parser, new[]{ "WatchedInSec", "Lenght", "LastWatchedUtc" }, null, null, null)
}));
Expand Down Expand Up @@ -292,6 +293,7 @@ public Session(Session other) : this() {
mediaId_ = other.mediaId_;
duration_ = other.duration_ != null ? other.duration_.Clone() : null;
mediaLenghtInSec_ = other.mediaLenghtInSec_;
fromDevice_ = other.fromDevice_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}

Expand Down Expand Up @@ -366,6 +368,17 @@ public double MediaLenghtInSec {
}
}

/// <summary>Field number for the "fromDevice" field.</summary>
public const int FromDeviceFieldNumber = 7;
private string fromDevice_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string FromDevice {
get { return fromDevice_; }
set {
fromDevice_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}

[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
return Equals(other as Session);
Expand All @@ -385,6 +398,7 @@ public bool Equals(Session other) {
if (MediaId != other.MediaId) return false;
if (!object.Equals(Duration, other.Duration)) return false;
if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(MediaLenghtInSec, other.MediaLenghtInSec)) return false;
if (FromDevice != other.FromDevice) return false;
return Equals(_unknownFields, other._unknownFields);
}

Expand All @@ -397,6 +411,7 @@ public override int GetHashCode() {
if (MediaId.Length != 0) hash ^= MediaId.GetHashCode();
if (duration_ != null) hash ^= Duration.GetHashCode();
if (MediaLenghtInSec != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(MediaLenghtInSec);
if (FromDevice.Length != 0) hash ^= FromDevice.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
Expand Down Expand Up @@ -434,6 +449,10 @@ public void WriteTo(pb::CodedOutputStream output) {
output.WriteRawTag(49);
output.WriteDouble(MediaLenghtInSec);
}
if (FromDevice.Length != 0) {
output.WriteRawTag(58);
output.WriteString(FromDevice);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
Expand All @@ -460,6 +479,9 @@ public int CalculateSize() {
if (MediaLenghtInSec != 0D) {
size += 1 + 8;
}
if (FromDevice.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(FromDevice);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
Expand Down Expand Up @@ -492,6 +514,9 @@ public void MergeFrom(Session other) {
if (other.MediaLenghtInSec != 0D) {
MediaLenghtInSec = other.MediaLenghtInSec;
}
if (other.FromDevice.Length != 0) {
FromDevice = other.FromDevice;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}

Expand Down Expand Up @@ -530,6 +555,10 @@ public void MergeFrom(pb::CodedInputStream input) {
MediaLenghtInSec = input.ReadDouble();
break;
}
case 58: {
FromDevice = input.ReadString();
break;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package snacktime.series.file;


message DownloadFileRequest {

string mediaFileId = 1;
}

message ResponseDownloadFile {
Expand Down
1 change: 1 addition & 0 deletions SnackTime.MediaServer.Proto/proto/storage.proto
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ message Session {
string mediaId = 4;
Duration duration = 5;
double mediaLenghtInSec = 6;
string fromDevice = 7;
}

message Duration {
Expand Down
27 changes: 24 additions & 3 deletions SnackTime.MediaServer/FileController.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,48 @@
using System;
using System.IO;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using Google.Protobuf;
using Grpc.Core;
using SnackTime.Core;
using SnackTime.Core.Media.Episodes;
using SnackTime.MediaServer.Service.File;
using File = System.IO.File;

namespace SnackTime.MediaServer
{
class FileController : SnackTime.MediaServer.Service.File.File.FileBase
{
private readonly EpisodeFileLookupProvider _episodeFileLookupProvider;

public FileController(EpisodeFileLookupProvider episodeFileLookupProvider)
{
_episodeFileLookupProvider = episodeFileLookupProvider;
}

public override async Task Download
(
DownloadFileRequest request,
IServerStreamWriter<ResponseDownloadFile> responseStream,
ServerCallContext context
)
{
var fileName = "Superstore.S04E15.1080p.WEB.H264-METCON.mkv";
var path = @"D:\Downloads\Torrents\Superstore.S04E15.1080p.WEB.H264-METCON\";
if (!MediaFileId.TryParse(request.MediaFileId, out var mediaFileId))
{
throw new Exception("Invalid mediaFileId");
}

var info = await _episodeFileLookupProvider.GetFileInfoForId(mediaFileId.FileId);


var backSlashIndex = info.Path.LastIndexOf("\\", StringComparison.CurrentCultureIgnoreCase);
var index = backSlashIndex > -1 ? backSlashIndex : info.Path.LastIndexOf("/", StringComparison.CurrentCultureIgnoreCase);

var fileName = info.Path.Substring(index + 1);

var chunkSize = 2048;
using (Stream source = File.OpenRead(path + fileName))
using (Stream source = File.OpenRead(info.Path))
{
byte[] buffer = new byte[chunkSize];
int bytesRead;
Expand Down
9 changes: 6 additions & 3 deletions SnackTime.WebApi/Controllers/FileController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@ public FileController(FileDownloadService fileDownloadService)
_fileDownloadService = fileDownloadService;
}

[HttpGet("download")]
public async Task<ActionResult> DownloadFile()
[HttpGet("download/{mediaFileIdStr}")]
public async Task<ActionResult> DownloadFile(string mediaFileIdStr)
{
await _fileDownloadService.DownloadFile();
if (!MediaFileId.TryParse(mediaFileIdStr, out var mediaFileId))
return BadRequest($"{nameof(mediaFileIdStr)} is invalid");

await _fileDownloadService.DownloadFile(mediaFileId);
return StatusCode(202);
}
}
Expand Down
25 changes: 17 additions & 8 deletions SnackTime.WebApi/Services/FileDownloadService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using SnackTime.Core;
using SnackTime.Core.Settings;
using SnackTime.MediaServer.Service.File;
using File = System.IO.File;

Expand All @@ -15,22 +17,31 @@ public class FileDownloadService
private readonly ILogger<FileDownloadService> _logger;
private readonly MediaServer.Service.File.File.FileClient _client;
private readonly FileService _fileService;
private readonly SettingsService _settingsService;

public FileDownloadService
(
ILogger<FileDownloadService> logger,
MediaServer.Service.File.File.FileClient client,
FileService fileService
FileService fileService,
SettingsService settingsService
)
{
_logger = logger;
_client = client;
_fileService = fileService;
_settingsService = settingsService;
}

public async Task DownloadFile()
public async Task DownloadFile(MediaFileId id)
{
var streamingCall = _client.Download(new DownloadFileRequest());
var streamingCall = _client.Download(new DownloadFileRequest
{
MediaFileId = id.ToString(),
});

var settings = _settingsService.Get();


double nrOfChunks = 0;

Expand All @@ -39,11 +50,9 @@ public async Task DownloadFile()

FileStream fileStream = null;

const string tempPath = "D:\\SnackTime\\Temp\\";
const int tempFileSize = 1024 * 10 * 10;

var fileName = "";
var fileOutputPath = "D:\\SnackTime\\";

_logger.LogInformation($"Starting to download file");

Expand All @@ -70,7 +79,7 @@ public async Task DownloadFile()
fileStream.Dispose();
}

fileStream = File.Create(tempPath + $"{fileName}.{currentTempFileIndex}.temp");
fileStream = File.Create(settings.TempFileDir + $"{fileName}.{currentTempFileIndex}.temp");

currentTempFileIndex++;
}
Expand All @@ -93,10 +102,10 @@ public async Task DownloadFile()

var sw = Stopwatch.StartNew();
var filePattern = $"{fileName}.*.temp";
await _fileService.CombineMultipleFilesIntoSingleFile(tempPath, filePattern, fileOutputPath + fileName);
await _fileService.CombineMultipleFilesIntoSingleFile(settings.TempFileDir, filePattern, settings.FileDir + fileName);

string hash;
using (Stream source = File.OpenRead(fileOutputPath + fileName))
using (Stream source = File.OpenRead(settings.FileDir + fileName))
using (var md5 = MD5.Create())
{
var byteHash = md5.ComputeHash(source);
Expand Down
Loading

0 comments on commit 755588b

Please sign in to comment.