Can i use putblock as append blob? - asp.net-core-webapi

So I am trying to upload file chunk by chunk...
Can PutBlock be used to append to an existing BlockBlob in Azure from this example...
I am uploading a 20mb file but finally, when I see it on the container it is 7mb and when I download blob it is broken... What am I doing wrong?
public async Task AppendBlobOnAsset(Stream stream, MediaServiceRequest request)
{
var cloudBlobContainer = new CloudBlobContainer(request.InputAssetStorageUri);
var blockBlob = cloudBlobContainer.GetBlockBlobReference(request.BlobName);
var blockList = new List<ListBlockItem>();
var blockListItems = new List<string>();
if (true)
{
var blocks = await blockBlob.DownloadBlockListAsync();
blockList = blocks.ToList();
blockListItems = blockList.Select(x => x.Name).ToList();
}
//string blockId = Guid.NewGuid().ToString("m");
string blockId = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes("0000005"));
blockBlob.PutBlock(blockId, stream, null);
blockListItems.Add(blockId);
blockBlob.PutBlockList(blockListItems);
}
using var file = File.OpenRead("C:\\Projects\\file.mp4");
int bytesRead;
var appendBlobMaxAppendBlockBytes = 4000000;
var buffer = new byte[appendBlobMaxAppendBlockBytes];
while ((bytesRead = await file.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
var newArray = new Span<byte>(buffer, 0, bytesRead).ToArray();
Stream stream = new MemoryStream(newArray);
stream.Position = 0;
await AppendBlobOnAsset(stream, request);
}

public async Task AppendBlobOnAssetAsync(int blockId, Stream stream, MediaServiceRequest request)
{
var cloudBlobContainer = new CloudBlobContainer(request.InputAssetStorageUri);
var blockBlob = cloudBlobContainer.GetBlockBlobReference(request.BlobName);
var blockItems = new List<ListBlockItem>();
var blockItemIds = new List<string>();
if (blockId > 0)
{
var blocks = await blockBlob.DownloadBlockListAsync();
blockItems = blocks.ToList();
blockItemIds = blockItems.Select(x => x.Name).ToList();
}
var Id = Convert.ToBase64String(Encoding.UTF8.GetBytes(blockId.ToString(CultureInfo.InvariantCulture).PadLeft(30, '0')));
blockBlob.PutBlock(Id, stream, null);
blockItemIds.Add(Id);
blockBlob.PutBlockList(blockItemIds);
}

Related

Zip Azure Storage Files and Return File from Web Api returns corrupted files when unzipped

Zip Azure Storage Files and Return File from Web Api returns corrupted files when unzipped, here is my code.
[HttpPost(nameof(DownloadFiles))]
public async Task<IActionResult> DownloadFiles(List<string> fileNames)
{
CloudBlockBlob blockBlob;
MemoryStream outputMemStream = new MemoryStream();
ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);
Stream blobStream;
zipStream.SetLevel(3); //0-9, 9 being the highest level of compression
string blobstorageconnection = _configuration.GetValue<string>("BlobConnectionString");
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(blobstorageconnection);
CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference(_configuration.GetValue<string>("BlobContainerName"));
using (MemoryStream memoryStream = new MemoryStream())
{
foreach (string fileName in fileNames)
{
blockBlob = cloudBlobContainer.GetBlockBlobReference(fileName);
await blockBlob.DownloadToStreamAsync(memoryStream);
ZipEntry newEntry = new ZipEntry(blockBlob.Name);
newEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(newEntry);
StreamUtils.Copy(memoryStream, zipStream, new byte[4096]);
zipStream.CloseEntry();
}
};
zipStream.IsStreamOwner = false; // False stops the Close also Closing the underlying stream.
zipStream.Close(); // Must finish the ZipOutputStream before using outputMemStream.
outputMemStream.Position = 0;
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StreamContent(outputMemStream);
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = "Documents.zip";
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentLength = outputMemStream.Length;
return File(outputMemStream, "application/octet-stream", "Documents.zip");
}
I am using SharpZipLib, and when I download the Zipped file and unzip it, the files contained in this file are corrupted.
Any advice? and thank you so much for your help
I was trying to zip files on my azure storage to download them as a zip, but the files in the downloaded zip are corrupted
[HttpPost(nameof(DownloadFiles))]
public async Task<IActionResult> DownloadFiles(List<string> fileNames)
{
MemoryStream outputMemStream = new MemoryStream();
ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);
zipStream.SetLevel(3); //0-9, 9 being the highest level of compression
byte[] bytes = null;
foreach (string fileName in fileNames)
{
var newEntry = new ZipEntry(fileName);
newEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(newEntry);
bytes = await CreateFile(fileName);
MemoryStream inStream = new MemoryStream(bytes);
StreamUtils.Copy(inStream, zipStream, new byte[4096]);
inStream.Close();
zipStream.CloseEntry();
}
zipStream.IsStreamOwner = false; // False stops the Close also Closing the underlying stream.
zipStream.Close(); // Must finish the ZipOutputStream before using outputMemStream.
outputMemStream.Position = 0;
return File(outputMemStream.ToArray(), "application/octet-stream", "directory.zip");
}
private async Task<byte[]> CreateFile(string fileName)
{
byte[] bytes = null;
await using (MemoryStream ms = new MemoryStream())
{
CloudBlockBlob blockBlob;
string blobstorageconnection = _configuration.GetValue<string>("BlobConnectionString");
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(blobstorageconnection);
CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference(_configuration.GetValue<string>("BlobContainerName"));
blockBlob = cloudBlobContainer.GetBlockBlobReference(fileName);
await blockBlob.DownloadToStreamAsync(ms);
bytes = ms.ToArray();
}
return bytes;
}

How to get Telegram channel Profile Photo with TelegramBotClient

I'm using C# TelegramBotClient library.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var bot = new TelegramBotClient("apiKey");
var chat = await bot.GetChatAsync("#channelName");
What should I do with BigFileId to get image?
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var bot = new TelegramBotClient("apiKey");
var chat = await bot.GetChatAsync("#channelName")
Telegram.Bot.Types.File p = await bot.GetFileAsync(chat.Photo.BigFileId);
string filePath = p.FilePath;
using (var outputStream = new MemoryStream())
{
var file = bot.GetInfoAndDownloadFileAsync(p.FileId, outputStream).GetAwaiter().GetResult();
var array = outputStream.ToArray();
using (var ms = new MemoryStream(array))
{
var image = Image.FromStream(ms);
image.Save("C:\\test\\image.jpg", ImageFormat.Jpeg);
}
}

Read Multiple Objects from Stream with Newtonsoft.Json

According to Reading multiple JSON objects on a JSON-RPC connection it shall be possible to send multiple requests one after another.
My problem is how to parse the requests with Newtonsoft.Json?
The JsonSerializer reads obviously more bytes than neccessary for deserializing the first request. The following snippet shows the problem:
class JsonRpcRequest
{
public int? id;
public string jsonrpc;
public string method;
public object #params;
}
class AddParam
{
public int a;
public int b;
}
static void Main(string[] args)
{
var p = new AddParam()
{
a = 100,
b = 200,
};
var request = new JsonRpcRequest()
{
jsonrpc = "2.0",
method = "Add",
#params = p,
};
var stream = new MemoryStream();
var reader = new StreamReader(stream);
var writer = new StreamWriter(stream);
var ser = new JsonSerializer();
request.id = 100;
ser.Serialize(writer, request);
writer.Flush();
// stream.Position is 68
request.id = 101;
ser.Serialize(writer, request);
writer.Flush();
// stream.Position is 136
stream.Position = 0;
// Stream holds
// {"id":100,"jsonrpc":"2.0","method":"Add","params":{"a":100,"b":200}}{"id":101,"jsonrpc":"2.0","method":"Add","params":{"a":100,"b":200}}
var r1 = ser.Deserialize(reader, typeof(JsonRpcRequest));
// r1 holds first Request
// But stream.Position is already 136
var r2 = ser.Deserialize(reader, typeof(JsonRpcRequest));
// r2 is null !!!???
}

How to upload a file on a server through api call in asp.net mvc

public ActionResult Index(PublishPost post, HttpPostedFileBase file)
{
var apiURL = "http://test.sa.com/rest/social/update/1161/upload?access_token=6fWV564kj3drlu7rATh8="
WebClient webClient = new WebClient();
byte[] responseBinary = webClient.UploadFile(apiUrl, file.FileName);
string response = Encoding.UTF8.GetString(responseBinary);
/* Giving error here. How to proceed?
}
I want to upload a single file to this url and the response is shown in the figure above. How to proceed further with the same in C#? Please help
Try your code like below.
public ActionResult Index(PublishPost post, HttpPostedFileBase file)
{
var apiURL = "http://test.sa.com/rest/social/update/1161/upload?access_token=6fWV564kj3drlu7rATh8="
using (HttpClient client = new HttpClient())
{
using (var content = new MultipartFormDataContent())
{
byte[] fileBytes = new byte[file.InputStream.Length + 1];
file.InputStream.Read(fileBytes, 0, fileBytes.Length);
var fileContent = new ByteArrayContent(fileBytes);
fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName = file.FileName };
content.Add(fileContent);
var result = client.PostAsync(apiURL, content).Result;
if (result.StatusCode == System.Net.HttpStatusCode.OK)
{
return new
{
code = result.StatusCode,
message = "Successful",
data = new
{
success = true,
filename = file.FileName
}
};
}
else
{
return new
{
code = result.StatusCode,
message = "Error"
};
}
}
}
}

Parameter has all propertys after webrequest

I have a really simple ASP.NET Api Controller with one method.
public HttpResponseMessage<User> Post(User user)
{
return new HttpResponseMessage<User>(new User() { Name = "New User at Server" });
}
My debugger says that the method is called but the problem is that the parameter "user" has all its content set to null; I am using Fiddler to look at request and response.. and all looks good.
This is my service code in the client.
public void AddUser(Models.User user, Action<Models.User> ShowResult)
{
var uiThreadScheduler = TaskScheduler.FromCurrentSynchronizationContext();
string url = "http://localhost:4921/User";
Uri uri = new Uri(url, UriKind.Absolute);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
var sendWebPost = Task.Factory.FromAsync<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream, null)
.ContinueWith(task =>
{
Tuple<string, string>[] stringToSend = { Tuple.Create<string, string>("user", ObjectToJson<Models.User>(user)) };
var bytesToSend = GetRequestBytes(stringToSend);
using (var stream = task.Result)
stream.Write(bytesToSend, 0, bytesToSend.Length);
}
).ContinueWith(task =>
{
Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null)
.ContinueWith<WebResponse>(task2 => { ValidateResponse(task2); return task2.Result; })
.ContinueWith<Models.User>(task3 => {return JsonToObject<Models.User>(task3);})
.ContinueWith(task4 => { TryClearWorking(); ShowResult(task4.Result); }, uiThreadScheduler);
});;
}
public static string ObjectToJson<T>(T obj) where T : class
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
MemoryStream stream = new MemoryStream();
StreamReader sr = new StreamReader(stream);
serializer.WriteObject(stream, obj);
sr.BaseStream.Position = 0;
string jsonString = sr.ReadToEnd();
return jsonString;
}
protected static byte[] GetRequestBytes(Tuple<string, string>[] postParameters)
{
if (postParameters == null || postParameters.Length == 0)
return new byte[0];
var sb = new StringBuilder();
foreach (var key in postParameters)
sb.Append(key.Item1 + "=" + key.Item2 + "&");
sb.Length = sb.Length - 1;
return Encoding.UTF8.GetBytes(sb.ToString());
}
Anyone who can give me some ideas where to start to look for errors.....
You need to set the Content-Length header.

Resources