Xamarin.forms ImageSource.FromFile doesn't work - c#

I'm using Xam.Plugin.Media to take a picture .
var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions()
{
Directory = "attachments",
Name = fileName,
CompressionQuality = 35
});
cam.Source = ImageSource.FromFile(file.Path);
above code does work !
file path is (file.Path):
/var/mobile/Containers/Data/Application/F3997E36-78EB-41AF-A37F-FC794BAF30EC/Documents/attachments/13c8ac4e57734a36bded2c2694e27495.jpg
but this code does not show picture in an Image control
var q = "/var/mobile/Containers/Data/Application/F3997E36-78EB-41AF-A37F-FC794BAF30EC/Documents/attachments/13c8ac4e57734a36bded2c2694e27495.jpg"
cam.Source = ImageSource.FromFile(q);

On iOS, this is the way to load file you saved before. This is because the system regenerate UDID every time the app relaunch.
public Stream LoadSampleStream(string filename) {
try
{
var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var filePath = Path.Combine(documentsPath, "Sample", filename);
return new FileStream(filePath, FileMode.Open);
}
catch(Exception ex) {
return null;
}
}

You need to save photo in gallery. When your user takes a photo it will still store temporary data, but also if needed make a copy to the public gallery
var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
{
SaveToAlbum = true
});
Get the public album path
var aPpath = file.AlbumPath;
Get private path
var path = file.Path;

Related

How to display image angular from .net core API and database

I would like to display a picture whose path it stores in the database
this is how it transfers the image file to the database.
public string UploadImage(IFormFile file)
{
if (file == null) throw new Exception("Pusty plik");
if (file.Length == 0)
{
throw new Exception("Pusty plik");
}
if (!ACCEPTED_FILE_TYPES.Any(s => s == Path.GetExtension(file.FileName).ToLower())) throw new Exception("Zły typ pliku");
if (string.IsNullOrWhiteSpace(host.WebRootPath))
{
host.WebRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
}
var uploadFilesPath = Path.Combine(host.WebRootPath, "images");
if (!Directory.Exists(uploadFilesPath))
Directory.CreateDirectory(uploadFilesPath);
var fileName = Guid.NewGuid().ToString() + Path.GetExtension(file.FileName);
var filePath = Path.Combine(uploadFilesPath, fileName);
using (var stream = new FileStream(filePath, FileMode.Create))
{
file.CopyToAsync(stream);
}
var path = Path.Combine(Directory.GetCurrentDirectory(), #"/wwwroot/images/", fileName);
return path;
}
here stores files:
https://zapodaj.net/a8829a7a3a90b.png.html
In your sample code I do not see path returning from database.
Also from security point of view it would be bad practice to return /wwwroot/images/ in response. You can create a folder on shared location and return shared location path.
Seems you question and same code isn't aligning.

Download image from json not complete

I have a json that contains a string and an image link. I want to download all of the images.
Code:
question.hasImg = hasimg;
if (question.hasImg == "1")
{
JsonArray gambar = groupObjectSoal["images"].GetArray();\
foreach (JsonValue groupValueGambar in gambar)
{
string imgSoal = groupValueGambar.GetString();
imgName = System.IO.Path.GetFileNameWithoutExtension(imgSoal);
DownloadGambar(imgSoal);
IReadOnlyList<DownloadOperation> downloads = null;
downloads = await BackgroundDownloader.GetCurrentDownloadsAsync();
int i = 0;
if (downloads.Count > 0)
{
gambardownloading = new string[downloads.Count];
foreach (DownloadOperation download in downloads)
{
// list download tryout
gambardownloading[i] = download.ResultFile.Name;
i++;
}
}
}
}
StorageFolder installedLocation = ApplicationData.Current.LocalFolder;
private async void DownloadGambar(string fileLocation)
{
var uri = new Uri(fileLocation);
var downloader = new BackgroundDownloader();
StorageFolder library = await installedLocation.CreateFolderAsync("library", CreationCollisionOption.OpenIfExists);
StorageFolder gambar = await library.CreateFolderAsync("gambar", CreationCollisionOption.OpenIfExists);
StorageFolder idName = await gambar.CreateFolderAsync(quiz.ID.ToString(), CreationCollisionOption.OpenIfExists);
StorageFile file = await idName.CreateFileAsync(imgName + ".JPG",
CreationCollisionOption.ReplaceExisting);
DownloadOperation download = downloader.CreateDownload(uri, file);
await GambarStartDownloadAsync(download);
}
private void GambarProgressCallback(DownloadOperation obj)
{
double progress
= ((double)obj.Progress.BytesReceived / obj.Progress.TotalBytesToReceive);
progress = Math.Round((double)progress, 2);
if (progress >= 1.0)
{
_activeDownload = null;
}
}
I'm having a problem, i.e. not all images are downloaded (for example there are 27 images, but only 25 images that were successfully downloaded). How to solve this problem?
I think you can use try-catch in image download method and I only add the succeed download file to list. And I add the thumb which show the download fail to the list to show the the item which download fail.
And then we can re-try download the file in background and set the image when download successfully.

Rally C#: How to upload a collection of attachments and associate with a user story?

I have refereed to the other examples on this website, but found a major difference in my method. (Please be patient)
I am trying to iterate over a directory of files and upload each file as an attachment and associate to a user story.
I am only able to attach 1 file for a user story as of now.
I see that every attachment has to be encoded to a base 64 string and it must have a the size in bytes.
Here is my code so far:
public void createUsWithAttachmentList(string workspace, string project, string userStoryName, string userStoryDescription)
{
//authentication
this.EnsureRallyIsAuthenticated();
//DynamicJSONObject for AttachmentContent
DynamicJsonObject myAttachmentContent = new DynamicJsonObject();
//Length calculated from Base64String converted back
int imageNumberBytes = 0;
//Userstory setup
DynamicJsonObject toCreate = new DynamicJsonObject();
toCreate["Workspace"] = workspace;
toCreate["Project"] = project;
toCreate["Name"] = userStoryName;
toCreate["Description"] = userStoryDescription;
//Trying to get a list of all the file paths within a given directory, this directory would contain .png files that need to be associated to a user story.
string[] attachmentPath = Directory.GetFiles("C:\\Users\\user\\Desktop\\RallyAttachments");
This foreach loop is confusing. I am trying to iterate over each file in the directory in order to convert it into a base64 string, and at the same time acquire the number of bytes for each file as an int.
foreach (string fileName in attachmentPath)
{
Image myImage = Image.FromFile(fileName);
string imageBase64String = imageToBase64(myImage, System.Drawing.Imaging.ImageFormat.Png);
imageNumberBytes = Convert.FromBase64String(imageBase64String).Length;
//I am stuck here to be exact because there are multiple imageBase64Strings due to the collection of files located inside the directory. AND the below line is wrong because I have a list of imageBase64Strings that were generated from iterating through the string[] attachmentPath.
myAttachmentContent[RallyField.content] = imageBase64String;
}
try
{
//create user story
CreateResult createUserStory = _api.Create(RallyField.attachmentContent, myAttachmentContent);
//create attachment
CreateResult myAttachmentContentCreateResult = _api.Create(RallyField.attachmentContent, myAttachmentContent);
String myAttachmentContentRef = myAttachmentContentCreateResult.Reference;
//DynamicJSONObject for Attachment Container
//I assume I would need a separate container for each file in my directory containing the attachments.
DynamicJsonObject myAttachment = new DynamicJsonObject();
myAttachment["Artifact"] = createUserStory.Reference;
myAttachment["Content"] = myAttachmentContentRef;
myAttachment["Name"] = "AttachmentFromREST.png";
myAttachment["Description"] = "Email Attachment";
myAttachment["ContentType"] = "image/png";
myAttachment["Size"] = imageNumberBytes;
//create & associate the attachment
CreateResult myAttachmentCreateResult = _api.Create(RallyField.attachment, myAttachment);
Console.WriteLine("Created User Story: " + createUserStory.Reference);
}
catch (WebException e)
{
Console.WriteLine(e.Message);
}
}
Note: I am planning on extending this method to support multiple file types, and I thing I would need to get the file type of each file in the directory and proceed accordingly.
Any ideas on how to go about writing this?
You've got all the parts implemented- we just need to move it around a little bit. Create the story once at the beginning, and then each time through the loop make a new AttachmentContent and a new Attachment for each file.
public void createUsWithAttachmentList(string workspace, string project, string userStoryName, string userStoryDescription)
{
//authentication
this.EnsureRallyIsAuthenticated();
//Userstory setup
DynamicJsonObject toCreate = new DynamicJsonObject();
toCreate["Workspace"] = workspace;
toCreate["Project"] = project;
toCreate["Name"] = userStoryName;
toCreate["Description"] = userStoryDescription;
//Create the story first
try
{
//create user story
CreateResult createUserStory = _api.Create(RallyField.userStory, toCreate);
//now loop over each file
string[] attachmentPath = Directory.GetFiles("C:\\Users\\user\\Desktop\\RallyAttachments");
foreach (string fileName in attachmentPath)
{
//DynamicJSONObject for AttachmentContent
DynamicJsonObject myAttachmentContent = new DynamicJsonObject();
Image myImage = Image.FromFile(fileName);
string imageBase64String = imageToBase64(myImage, System.Drawing.Imaging.ImageFormat.Png);
int imageNumberBytes = Convert.FromBase64String(imageBase64String).Length;
myAttachmentContent[RallyField.content] = imageBase64String;
//create the AttachmentConent
CreateResult myAttachmentContentCreateResult = _api.Create(RallyField.attachmentContent, myAttachmentContent);
String myAttachmentContentRef = myAttachmentContentCreateResult.Reference;
//create an Attachment to associate to story
DynamicJsonObject myAttachment = new DynamicJsonObject();
myAttachment["Artifact"] = createUserStory.Reference;
myAttachment["Content"] = myAttachmentContentRef;
myAttachment["Name"] = "AttachmentFromREST.png";
myAttachment["Description"] = "Email Attachment";
myAttachment["ContentType"] = "image/png";
myAttachment["Size"] = imageNumberBytes;
//create & associate the attachment
CreateResult myAttachmentCreateResult = _api.Create(RallyField.attachment, myAttachment);
}
}
catch (WebException e)
{
Console.WriteLine(e.Message);
}
}

C# Download the sound of a youtube video

I can download a video from youtube but I want the sound only. How can I do that?
Code I have for downloading the video (Using VideoLibrary):
YouTube youtube = YouTube.Default;
Video vid = youtube.GetVideo(txt_youtubeurl.Text);
System.IO.File.WriteAllBytes(source + vid.FullName, vid.GetBytes());
Install the NuGet packages: MediaToolkit and VideoLibrary, it will allow you to do the conversion by file extension.
var source = #"<your destination folder>";
var youtube = YouTube.Default;
var vid = youtube.GetVideo("<video url>");
File.WriteAllBytes(source + vid.FullName, vid.GetBytes());
var inputFile = new MediaFile { Filename = source + vid.FullName };
var outputFile = new MediaFile { Filename = $"{source + vid.FullName}.mp3" };
using (var engine = new Engine())
{
engine.GetMetadata(inputFile);
engine.Convert(inputFile, outputFile);
}
The above code works awesome you don't need to download the video first I created this procedure so when rookies like myself see this makes it easier to use.
You need the nuget packages MediaToolkit and VideoLibrary.
example url: https://www.youtube.com/watch?v=lzm5llVmR2E
example path just needs a path to save file to.
just add the name of the mp3 file to save
Hope this helps someone I have tested this code;
private void SaveMP3(string SaveToFolder, string VideoURL, string MP3Name)
{
var source = #SaveToFolder;
var youtube = YouTube.Default;
var vid = youtube.GetVideo(VideoURL);
File.WriteAllBytes(source + vid.FullName, vid.GetBytes());
var inputFile = new MediaFile { Filename = source + vid.FullName };
var outputFile = new MediaFile { Filename = $"{MP3Name}.mp3" };
using (var engine = new Engine())
{
engine.GetMetadata(inputFile);
engine.Convert(inputFile, outputFile);
}
}
based on this topic, i have developed a simple and dumb program to Download a youtube playlist. Hope this helps someone. It's just a Main.cs file: Youtube Playlist Downloader - Mp4 & Mp3
Ok found a better way the above code didn't normalize the audio posting it for others.
First Add Nuget package: https://www.nuget.org/packages/NReco.VideoConverter/
To Convert MP4 to MP3
// Client
var client = new YoutubeClient();
var videoId = NormalizeVideoId(txtFileURL.Text);
var video = await client.GetVideoAsync(videoId);
var streamInfoSet = await client.GetVideoMediaStreamInfosAsync(videoId);
// Get the best muxed stream
var streamInfo = streamInfoSet.Muxed.WithHighestVideoQuality();
// Compose file name, based on metadata
var fileExtension = streamInfo.Container.GetFileExtension();
var fileName = $"{video.Title}.{fileExtension}";
// Replace illegal characters in file name
fileName = RemoveIllegalFileNameChars(fileName);
tmrVideo.Enabled = true;
// Download video
txtMessages.Text = "Downloading Video please wait ... ";
//using (var progress = new ProgressBar())
await client.DownloadMediaStreamAsync(streamInfo, fileName);
// Add Nuget package: https://www.nuget.org/packages/NReco.VideoConverter/ To Convert MP4 to MP3
if (ckbAudioOnly.Checked)
{
var Convert = new NReco.VideoConverter.FFMpegConverter();
String SaveMP3File = MP3FolderPath + fileName.Replace(".mp4", ".mp3");
Convert.ConvertMedia(fileName, SaveMP3File, "mp3");
//Delete the MP4 file after conversion
File.Delete(fileName);
LoadMP3Files();
txtMessages.Text = "File Converted to MP3";
tmrVideo.Enabled = false;
txtMessages.BackColor = Color.White;
if (ckbAutoPlay.Checked) { PlayFile(SaveMP3File); }
return;
}
I like the idea of using a method. I tried SaveMP3() but it had some problems.
This worked for me: `
private void SaveMP3(string SaveToFolder, string VideoURL, string MP3Name)
{
string source = SaveToFolder;
var youtube = YouTube.Default;
var vid = youtube.GetVideo(VideoURL);
string videopath = Path.Combine(source, vid.FullName);
File.WriteAllBytes(videopath, vid.GetBytes());
var inputFile = new MediaFile { Filename = Path.Combine(source, vid.FullName) };
var outputFile = new MediaFile { Filename = Path.Combine(source , $"{MP3Name}.mp3") };
using (var engine = new Engine())
{
engine.GetMetadata(inputFile);
engine.Convert(inputFile, outputFile);
}
File.Delete(Path.Combine(source, vid.FullName));
}
`

Auto Copying multiple images and show tile notifications?

This is my code for Windows 8 metro apps, in which I copy 1 image from the local folder to my app storage folder and then it shows a tile notification. Please help me to auto copy all images from Picture Library and then these images shown in tile notifications.
i don't know how to access or copy all images from Picture Library... no user interface for copy images.
public sealed partial class BlankPage : Page
{
string imageRelativePath = String.Empty;
public BlankPage()
{
this.InitializeComponent();
CopyImages();
}
public async void CopyImages()
{
FileOpenPicker picker = new Windows.Storage.Pickers.FileOpenPicker();
picker.ViewMode = PickerViewMode.Thumbnail;
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".jpeg");
picker.FileTypeFilter.Add(".png");
picker.CommitButtonText = "Copy";
StorageFile file = await picker.PickSingleFileAsync();
StorageFile newFile = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(file.Name);
await file.CopyAndReplaceAsync(newFile);
this.imageRelativePath = newFile.Path.Substring(newFile.Path.LastIndexOf("\\") + 1);
IWideTileNotificationContent tileContent = null;
ITileWideImage wideContent = TileContentFactory.CreateTileWideImage();
wideContent.RequireSquareContent = false;
wideContent.Image.Src = "ms-appdata:///local/" + this.imageRelativePath;
wideContent.Image.Alt = "App data";
tileContent = wideContent;
tileContent.RequireSquareContent = false;
TileUpdateManager.CreateTileUpdaterForApplication().Update(tileContent.CreateNotification());
}
}
1st give the path of images folder and then make a list of these images through IReadOnlyList, and set loop on copy images to end, after that just set timer on TileUpdateManager. and it will work.
to enumerate files in PicturesLibrary:
// from my sample app "MetroContractSample" http://metrocontractsample.codeplex.com/documentation
var queryOptions = new QueryOptions(CommonFileQuery.DefaultQuery, new[] { ".jpg", ".png", ".bmp", ".gif", }) { FolderDepth = FolderDepth.Deep, };
StorageFileQueryResult query = KnownFolders.PicturesLibrary.CreateFileQueryWithOptions(queryOptions);
var fileInfoFactory = new FileInformationFactory(query, ThumbnailMode.SingleItem);
IReadOnlyList<FileInformation> fileInfoList = await fileInfoFactory.GetFilesAsync();
NOTE: You have to declare the Capability for PicturesLibrary in Package.appxmanifest.

Categories