I'm writing a telegram bot that takes jpg from it's users and sends it back as stickers.
I did this correctly by downloading jpg, change the extension of file to png and upload and send it back as a sticker message to the user. as shown below:
var file = await bot.GetFileAsync(update.Message.Photo.LastOrDefault()?.FileId);
var filename = file.FileId + "." + file.FilePath.Split('.').Last();
var pngFileName = filename.Split('.')[0] + ".png";
using (var saveImageStream = System.IO.File.Open(pngFileName, FileMode.Create))
{
await bot.DownloadFileAsync(file.FilePath, saveImageStream);
await bot.SendTextMessageAsync(update.Message.Chat.Id, "please wait...");
}
using (var stream = System.IO.File.Open(pngFileName, FileMode.Open))
{
await bot.SendStickerAsync(update.Message.Chat.Id, stream);
}
but the these stickers don't load in telegram on IOS devices and this code just works for telegram users on android. I tried to just changing the extension of jpg file to webp but it didn't work.
after that I downloaded the standard telegram stickers and found that the standard format of stickers in telegram is webp files.
now I want to know how can I convert received jpg file to webp file.
I searched alot and just find this , found here .
using (Image image = Image.FromFile("image.jpg"))
{
Bitmap bitmap = new Bitmap(image);
WebPFormat.SaveToFile("image.webp", bitmap);
}
I added it's files to my project and I added "using LibwebpSharp;" at the top of my code, but when I add it's sample code, the VS cannot find "WebpFormat" class.
please help me and answer my question:
"How can I convert jpg to webp in C# telegram bot?"
thank you
I solved this problem in this way:
I installed Imazen.WebP nuget.
I downloaded the 32bit dll from here and added it to release folder.
I added "using Imazen.WebP;in top of my code
I used this code to convert jpg to webp.
var file = await bot.GetFileAsync(update.Message.Photo.LastOrDefault()?.FileId);
var jpgFileName = file.FileId + ".jpg";
using (var saveImageStream = System.IO.File.Open(jpgFileName,FileMode.Create))
{
await bot.DownloadFileAsync(file.FilePath, saveImageStream);
await bot.SendTextMessageAsync(update.Message.Chat.Id, "please wait...");
}
var webpFileName = file.FileId + ".webp";
using (Bitmap bitmap = new Bitmap(jpgFileName))
{
using (var saveImageStream = System.IO.File.Open(webpFileName, FileMode.Create))
{
var encoder = new SimpleEncoder();
encoder.Encode(bitmap, saveImageStream, 20);
}
}
using (var stream = System.IO.File.Open(webpFileName, FileMode.Open))
{
await bot.SendStickerAsync(update.Message.Chat.Id, stream);
}
System.IO.File.Delete(jpgFileName);
System.IO.File.Delete(webpFileName);
Install the following packages first using Visual Studio's NuGet package manager:
Install-Package System.Drawing.Common
Install-Package ImageProcessor
Install-Package ImageProcessor.Plugins.WebP
Then use this code for conversion:
using (var webPFileStream = new FileStream(WebpFilePath, FileMode.Create))
{
using (ImageFactory imageFactory = new ImageFactory(preserveExifData: false))
{
imageFactory.Load(File.OpenRead(OriginalImagePath))
.Format(new WebPFormat())
.Quality(100)
.Save(webPFileStream);
}
}
Imageprocessor looks like a good library to convert the image. There is a Webp plugin.
Here is an article that may help.
Code example:
using ImageProcessor;
using ImageProcessor.Plugins.WebP.Imaging.Formats;
using (var normalFileStream = new FileStream(normalImagePath, FileMode.Create))
using (var webPFileStream = new FileStream(webPImagePath, FileMode.Create))
using (var imageFactory = new ImageFactory(preserveExifData: false))
{
imageFactory.Load(image.OpenReadStream())
.Format(new WebPFormat())
.Quality(50)
.Save(webPFileStream);
}
Related
I'm trying to share a local image loacted in my Resources/Drawables folder in Android.
I'm using Xamarin and the Xamarin.Essentials plugin.
So there is this function:
await Share.RequestAsync(new ShareFileRequest
{
Title = Title,
File = new ShareFile(file)
});
So for the File I need the Path to the File from the Drawable Folder.
I have tried so much variations.
For example:
var file = Android.Net.Uri.Parse("android.resource://" + Android.App.Application.Context.PackageName + "/" + Resource.Drawable.image).Path;
But I always get an error, that the file is not found.
What I'm doing wrong?
Thanks in advance
Because Resources don't have file paths, as #Jason said I saved the image in another accesible file.
So I don't know if this is the best solution, but it works for me:
Drawable drawable = ResourcesCompat.GetDrawable(Resources, Resource.Drawable.image, null);
Bitmap bitmap = ((BitmapDrawable)drawable).Bitmap;
byte[] imgByteArray;
using (var stream = new MemoryStream())
{
bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
imgByteArray = stream.ToArray();
}
var file = System.IO.Path.Combine(FileSystem.CacheDirectory, "share.png");
File.WriteAllBytes(file, imgByteArray);
await Share.RequestAsync(new ShareFileRequest
{
Title = "Share",
File = new ShareFile(file)
});
On my Xamarin android application i create db path using the "System.Environment.SpecialFolder.Personal".
I have an existing sqlite database. Where in the project and with what properties must i include the database to be used in the peronal folder?
You can use Xamarin.Essentials to access your read-only bundle/asset resource and copy it without have to use native platform code or if you are coding within an Xamarin.Android project, you can directly use Android.Content's Assets
So assuming you have a database in your Android Assets folder:
Assets
db.sqlite
Xamarin Essentials / NetStd2.0 Code Example:
var copyToLocationPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "db.sqlite");
if (!File.Exists(copyToLocationPath))
{
using (var assetStream = await Xamarin.Essentials.FileSystem.OpenAppPackageFileAsync("db.sqlite"))
using (var fileStream = new FileStream(copyToLocationPath, FileMode.Create, FileAccess.Write))
{
await assetStream.CopyToAsync(fileStream);
}
}
var connection = new SqliteConnection(copyToLocationPath);
Xamarin Android code sample (Directly use Assets):
var copyToLocationPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "db.sqlite");
if (!File.Exists(copyToLocationPath))
{
using (var assetStream = Assets.Open("db.sqlite"))
using (var fileStream = new FileStream(copyToLocationPath, FileMode.Create, FileAccess.Write))
{
await assetStream.CopyToAsync(fileStream);
}
}
I made an application to save photos on the phone.
public void DownloadImage(string linkbitmap, string title)
{
Bitmap bitmap = GetImageBitmapFromUrl(linkbitmap).Result;
var path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures + "/Tsundere");
var complete = path.AbsolutePath;
var filepatch = System.IO.Path.Combine(complete, title + ".jpg");
var filestream = new FileStream(filepatch, FileMode.Create);
bitmap.Compress(Bitmap.CompressFormat.Png, 100, filestream);
filestream.Close();
}
The pictures are displayed in the file manager, but in the example the discord application does not have them. I have to restart the phone to be visible. How to make photos immediately visible in other applications, such as photos from the camera or photos downloaded from facebook?
I solve this problem. Just add MediaScannerConnection.ScanFile(Android.App.Application.Context, new string[] {path}, null, null);in the code
description this class https://developer.xamarin.com/api/type/Android.Media.MediaScannerConnection/
Construct an Intent action (Intent.ActionMediaScannerScanFile) with a uri that includes the file path:
using (var file = new Java.IO.File(path))
using (var uri = Android.Net.Uri.FromFile(file))
{
var scanFileIntent = new Intent(Intent.ActionMediaScannerScanFile, uri);
SendBroadcast(scanFileIntent);
}
FYI: You can create/register a BroadcastReceiver that listens for Intent.ActionMediaScannerFinished to determine when the media scanner is done processing your request.
I hope anyone can help me, I'am new in C, I am working on making web APIs that sends files from server based on an input , When I enter an ID , I get all files related to that ID (Indesign files, jpegs, pngs, illustator files ...)
I use Postman to get the resulat and it looks like the attached fileenter image description here :
I have to copy each link and paste it to address bar to download the file.
What I want is to have only one file (Zip) that contains all files.
Is that even doable ? Thanks
I found solution and it's returning a zipfile with the correct files, the issue now that these files have 0Kb size , Help please ?
Here's my code
``
MemoryStream archiveStream = new MemoryStream();
using (ZipArchive archiveFile = new ZipArchive(archiveStream, ZipArchiveMode.Create, true))
{
foreach (var item in assetsNotDuplicated)
{
// create file streams
// add the stream to zip file
var entry = archiveFile.CreateEntry(item.Name);
using (StreamWriter sw = new StreamWriter(entry.Open()))
{
sw.Write(item.Url);
}
}
}
HttpResponseMessage responseMsg = new HttpResponseMessage(HttpStatusCode.OK);
responseMsg.Content = new ByteArrayContent(archiveStream.ToArray());
//archiveStream.Dispose();
responseMsg.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = "allfiles.zip" };
responseMsg.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
return responseMsg;
}
I want to download a .xlsx file from below address.
http://members.tsetmc.com/tsev2/excel/MarketWatchPlus.aspx?d=1396-08-08
by clicking on the link automatically a file will be downloaded by the browser. I tried to download the file from this codes:
using (var client = new WebClient())
{
client.DownloadFile("http://members.tsetmc.com/tsev2/excel/MarketWatchPlus.aspx?d=1396-08-08", #"D:\Archive\1396-08-08.xlsx");
}
But it will download a weird file different from the file downloaded by the browser at first step.
Also I tried :
System.Diagnostics.Process.Start(
"http://members.tsetmc.com/tsev2/excel/MarketWatchPlus.aspx?d=0");
But this code has two disadvantages:
1- It opens a browser which is not required.
2- I can't determine any path or file name for the downloaded file.
I want to gain exactly the same file that will be downloaded by clicking on the above link address.
How can I download my required file?
Lasse Vågsæther Karlsen is correct. Your browser is smart enough to decompress the file because the response contains the header:
content-encoding:"gzip"
You can download and decompress the file with this code (adjust accordingly for your file name, path, etc.)
void Main()
{
using (var client = new WebClient())
{
client.Headers.Add("accept", "*/*");
byte[] filedata = client.DownloadData("http://members.tsetmc.com/tsev2/excel/MarketWatchPlus.aspx?d=1396-08-08");
using (MemoryStream ms = new MemoryStream(filedata))
{
using (FileStream decompressedFileStream = File.Create("c:\\deleteme\\test.xlsx"))
{
using (GZipStream decompressionStream = new GZipStream(ms, CompressionMode.Decompress))
{
decompressionStream.CopyTo(decompressedFileStream);
}
}
}
}
}