- fix file Uploader

- refactor file uploader
- added test for file uploading
This commit is contained in:
Ilya P 2016-10-23 13:02:44 +03:00
parent 7fd0413c7e
commit 1d6035aeb7
4 changed files with 213 additions and 106 deletions

View file

@ -7,112 +7,130 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using TeleSharp.TL; using TeleSharp.TL;
using TeleSharp.TL.Upload; using TeleSharp.TL.Upload;
using TLSharp.Core.Utils;
namespace TLSharp.Core.Requests namespace TLSharp.Core.Requests
{ {
public class UploadHelper public static class UploadHelper
{ {
public static async Task<TLAbsInputFile> Uploader(string name,StreamReader reader,TelegramClient client) private static string GetFileHash(byte[] data)
{ {
if (reader.BaseStream.Length < 10 * 1024 * 1024) string md5_checksum;
return await SmallFileUpload(name, reader, client); using (var md5 = MD5.Create())
{
var hash = md5.ComputeHash(data);
var hashResult = new StringBuilder(hash.Length * 2);
foreach (byte t in hash)
hashResult.Append(t.ToString("x2"));
md5_checksum = hashResult.ToString();
}
return md5_checksum;
}
public static async Task<TLAbsInputFile> UploadFile(this TelegramClient client, string name, StreamReader reader)
{
const long tenMb = 10 * 1024 * 1024;
return await UploadFile(name, reader, client, reader.BaseStream.Length >= tenMb);
}
private static byte[] GetFile(StreamReader reader)
{
var file = new byte[reader.BaseStream.Length];
using (reader)
{
reader.BaseStream.Read(file, 0, (int)reader.BaseStream.Length);
}
return file;
}
private static Queue<byte[]> GetFileParts(byte[] file)
{
var fileParts = new Queue<byte[]>();
const int maxFilePart = 512 * 1024;
using (var stream = new MemoryStream(file))
{
while (stream.Position != stream.Length)
{
if ((stream.Length - stream.Position) > maxFilePart)
{
var temp = new byte[maxFilePart];
stream.Read(temp, 0, maxFilePart);
fileParts.Enqueue(temp);
}
else
{
var length = stream.Length - stream.Position;
var temp = new byte[length];
stream.Read(temp, 0, (int)(length));
fileParts.Enqueue(temp);
}
}
}
return fileParts;
}
private static async Task<TLAbsInputFile> UploadFile(string name, StreamReader reader,
TelegramClient client, bool isBigFileUpload)
{
var file = GetFile(reader);
var fileParts = GetFileParts(file);
int partNumber = 0;
int partsCount = fileParts.Count;
long file_id = BitConverter.ToInt64(Helpers.GenerateRandomBytes(8), 0);
while (fileParts.Count != 0)
{
var part = fileParts.Dequeue();
if (isBigFileUpload)
{
await client.SendRequestAsync<bool>(new TLRequestSaveBigFilePart
{
file_id = file_id,
file_part = partNumber,
bytes = part,
file_total_parts = partsCount
});
}
else
{
await client.SendRequestAsync<bool>(new TLRequestSaveFilePart
{
file_id = file_id,
file_part = partNumber,
bytes = part
});
}
partNumber++;
}
if (isBigFileUpload)
{
return new TLInputFileBig
{
id = file_id,
name = name,
parts = partsCount
};
}
else else
return await BigFileUpload(name, reader, client);
}
private static async Task<TLInputFile> SmallFileUpload(string name, StreamReader reader, TelegramClient client)
{
var file = new byte[reader.BaseStream.Length];
reader.BaseStream.Read(file, 0, (int)reader.BaseStream.Length);
string hash;
using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
{ {
hash = Convert.ToBase64String(md5.ComputeHash(file)); return new TLInputFile
}
reader = null;
var stream = new MemoryStream(file);
Queue<byte[]> parts = new Queue<byte[]>();
while (!(stream.Position == stream.Length))
{
if ((stream.Length - stream.Position) > 512 *1024)
{ {
byte[] temp = new byte[512]; id = file_id,
stream.Read(temp, 0, 512 * 1024); name = name,
parts.Enqueue(temp); parts = partsCount,
} md5_checksum = GetFileHash(file)
else };
{
byte[] temp = new byte[512];
stream.Read(temp, 0, (int)(stream.Length - stream.Position));
parts.Enqueue(temp);
}
} }
stream = null;
int partnumber = 0;
long file_id = BitConverter.ToInt64(RandomByteArray(8), 0);
while (parts.Count != 0)
{
var part = parts.Dequeue();
TLRequestSaveFilePart save = new TLRequestSaveFilePart();
save.file_id = file_id;
save.file_part = partnumber;
save.bytes = part;
await client.SendRequestAsync<bool>(save);
partnumber++;
}
TLInputFile returnFile = new TLInputFile();
returnFile.id = file_id;
returnFile.name = name;
returnFile.parts = parts.Count;
returnFile.md5_checksum = hash;
return returnFile;
}
private static async Task<TLInputFileBig> BigFileUpload(string name, StreamReader reader, TelegramClient client)
{
var file = new byte[reader.BaseStream.Length];
reader.BaseStream.Read(file, 0, (int)reader.BaseStream.Length);
reader = null;
var stream = new MemoryStream(file);
Queue<byte[]> parts = new Queue<byte[]>();
while (!(stream.Position == stream.Length))
{
if ((stream.Length - stream.Position) > 512 * 1024)
{
byte[] temp = new byte[512];
stream.Read(temp, 0, 512 * 1024);
parts.Enqueue(temp);
}
else
{
byte[] temp = new byte[512];
stream.Read(temp, 0, (int)(stream.Length - stream.Position));
parts.Enqueue(temp);
}
}
stream = null;
int partnumber = 0;
long file_id = BitConverter.ToInt64(RandomByteArray(8), 0);
while (parts.Count != 0)
{
var part = parts.Dequeue();
TLRequestSaveBigFilePart save = new TLRequestSaveBigFilePart();
save.file_id = file_id;
save.file_part = partnumber;
save.bytes = part;
save.file_total_parts = parts.Count;
await client.SendRequestAsync<bool>(save);
partnumber++;
}
TLInputFileBig returnFile = new TLInputFileBig();
returnFile.id = file_id;
returnFile.name = name;
returnFile.parts = parts.Count;
return returnFile;
}
private static byte[] RandomByteArray(int count)
{
var temp = new byte[count];
Random random = new Random();
random.NextBytes(temp);
return temp;
} }
} }
} }

View file

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web;
using TeleSharp.TL; using TeleSharp.TL;
using TeleSharp.TL.Auth; using TeleSharp.TL.Auth;
using TeleSharp.TL.Contacts; using TeleSharp.TL.Contacts;
@ -10,6 +11,8 @@ using TeleSharp.TL.Messages;
using TLSharp.Core.Auth; using TLSharp.Core.Auth;
using TLSharp.Core.MTProto.Crypto; using TLSharp.Core.MTProto.Crypto;
using TLSharp.Core.Network; using TLSharp.Core.Network;
using TLSharp.Core.Requests;
using TLSharp.Core.Utils;
namespace TLSharp.Core namespace TLSharp.Core
{ {
@ -53,7 +56,15 @@ namespace TLSharp.Core
//set-up layer //set-up layer
var config = new TLRequestGetConfig(); var config = new TLRequestGetConfig();
var request = new TLRequestInitConnection() { api_id = _apiId, app_version = "1.0.0", device_model = "PC", lang_code = "en", query = config, system_version = "Win 10.0" }; var request = new TLRequestInitConnection()
{
api_id = _apiId,
app_version = "1.0.0",
device_model = "PC",
lang_code = "en",
query = config,
system_version = "Win 10.0"
};
var invokewithLayer = new TLRequestInvokeWithLayer() { layer = 57, query = request }; var invokewithLayer = new TLRequestInvokeWithLayer() { layer = 57, query = request };
await _sender.Send(invokewithLayer); await _sender.Send(invokewithLayer);
await _sender.Receive(invokewithLayer); await _sender.Receive(invokewithLayer);
@ -165,14 +176,12 @@ namespace TLSharp.Core
if (!IsUserAuthorized()) if (!IsUserAuthorized())
throw new InvalidOperationException("Authorize user first!"); throw new InvalidOperationException("Authorize user first!");
long uniqueId = Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds);
return await SendRequestAsync<TLAbsUpdates>( return await SendRequestAsync<TLAbsUpdates>(
new TLRequestSendMessage() new TLRequestSendMessage()
{ {
peer = peer, peer = peer,
message = message, message = message,
random_id = uniqueId random_id = Helpers.GenerateRandomLong()
}); });
} }
@ -193,6 +202,37 @@ namespace TLSharp.Core
new TLRequestGetDialogs() { offset_date = 0, offset_peer = peer, limit = 100 }); new TLRequestGetDialogs() { offset_date = 0, offset_peer = peer, limit = 100 });
} }
public async Task<TLAbsUpdates> SendUploadedPhoto(TLAbsInputPeer peer, TLAbsInputFile file, string caption)
{
return await SendRequestAsync<TLAbsUpdates>(new TLRequestSendMedia()
{
random_id = Helpers.GenerateRandomLong(),
background = false,
clear_draft = false,
media = new TLInputMediaUploadedPhoto() { file = file, caption = caption },
peer = peer
});
}
public async Task<TLAbsUpdates> SendUploadedDocument(
TLAbsInputPeer peer, TLAbsInputFile file, string caption, string mimeType, TLVector<TLAbsDocumentAttribute> attributes)
{
return await SendRequestAsync<TLAbsUpdates>(new TLRequestSendMedia()
{
random_id = Helpers.GenerateRandomLong(),
background = false,
clear_draft = false,
media = new TLInputMediaUploadedDocument()
{
file = file,
caption = caption,
mime_type = mimeType,
attributes = attributes
},
peer = peer
});
}
private void OnUserAuthenticated(TLUser TLUser) private void OnUserAuthenticated(TLUser TLUser)
{ {
_session.TLUser = TLUser; _session.TLUser = TLUser;

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -68,6 +68,11 @@
<Name>TLSharp.Core</Name> <Name>TLSharp.Core</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="data\cat.jpg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Choose> <Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'"> <When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup> <ItemGroup>

View file

@ -6,6 +6,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using TeleSharp.TL; using TeleSharp.TL;
using TeleSharp.TL.Channels; using TeleSharp.TL.Channels;
@ -15,6 +16,8 @@ using TLSharp.Core;
using TLSharp.Core.Auth; using TLSharp.Core.Auth;
using TLSharp.Core.MTProto; using TLSharp.Core.MTProto;
using TLSharp.Core.Network; using TLSharp.Core.Network;
using TLSharp.Core.Requests;
using TLSharp.Core.Utils;
namespace TLSharp.Tests namespace TLSharp.Tests
{ {
@ -37,7 +40,7 @@ namespace TLSharp.Tests
private int apiId = 0; private int apiId = 0;
[TestInitialize] [TestInitialize]
public void Init() public void Init()
{ {
// Setup your phone numbers in app.config // Setup your phone numbers in app.config
@ -117,7 +120,49 @@ namespace TLSharp.Tests
await client.SendMessageAsync(new TLInputPeerChannel() { channel_id = chat.id, access_hash = chat.access_hash.Value }, "TEST MSG"); await client.SendMessageAsync(new TLInputPeerChannel() { channel_id = chat.id, access_hash = chat.access_hash.Value }, "TEST MSG");
} }
[TestMethod] [TestMethod]
public async Task SendPhotoToContactTest()
{
var client = new TelegramClient(apiId, apiHash);
await client.ConnectAsync();
var result = await client.GetContactsAsync();
var user = result.users.lists
.Where(x => x.GetType() == typeof(TLUser))
.Cast<TLUser>()
.FirstOrDefault(x => x.phone == NumberToSendMessage);
var fileResult = (TLInputFile)await client.UploadFile("cat.jpg", new StreamReader("data/cat.jpg"));
await client.SendUploadedPhoto(new TLInputPeerUser() {user_id = user.id}, fileResult, "kitty");
}
[TestMethod]
public async Task SendBigFileToContactTest()
{
var client = new TelegramClient(apiId, apiHash);
await client.ConnectAsync();
var result = await client.GetContactsAsync();
var user = result.users.lists
.Where(x => x.GetType() == typeof(TLUser))
.Cast<TLUser>()
.FirstOrDefault(x => x.phone == NumberToSendMessage);
var fileResult = (TLInputFileBig)await client.UploadFile("some.zip", new StreamReader("C:\\PetProjects\\TelegramBotSample.zip"));
await client.SendUploadedDocument(
new TLInputPeerUser() {user_id = user.id},
fileResult,
"some zips",
"application/zip",
new TLVector<TLAbsDocumentAttribute>());
}
[TestMethod]
public async Task SignUpNewUser() public async Task SignUpNewUser()
{ {
var client = new TelegramClient(apiId, apiHash); var client = new TelegramClient(apiId, apiHash);
@ -143,6 +188,5 @@ namespace TLSharp.Tests
var result = await client.IsPhoneRegisteredAsync(NumberToAuthenticate); var result = await client.IsPhoneRegisteredAsync(NumberToAuthenticate);
Assert.IsTrue(result); Assert.IsTrue(result);
} }
} }
} }