Download image from json not complete - c#

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.

Related

.NET 7 System.IO.FileNotFoundException: Could not find file

This is my first time asking around here, so sorry if it's not worded very well.
I have a blazor WebAssembly project with MudBlazor, and when I try to upload files to save them into a database, it appears the next error message in the browser console.
System.IO.FileNotFoundException: Could not find file
When the user uploads the files I call the next method to save the files into IList<IBrowserFile>.
IList<IBrowserFile> Files = new List<IBrowserFile>();
private void OnInputFileChanged(InputFileChangeEventArgs e)
{
var files = e.GetMultipleFiles();
foreach(var file in files)
{
Files.Add(file);
}
}
Once the user has uploaded all the files, they click on a button that call the next method to upload it into a database.
[Inject] protected ISnackbar Snackbar { get; set; } = default!;
private async void Upload()
{
List<string>? notUploadFiles = null;
foreach(var file in Files)
{
byte[] fileBytes = File.ReadAllBytes(destPath + file.Name);
string extn = new FileInfo(file.Name).Extension;
var addArchivoTarea = new AddArchivoTareaRequestDTO(Tarea.Id, fileBytes, extn);
var successResponse = await HttpTareas.AddArchivoToTareaAsync(addArchivoTarea);
if (!successResponse)
{
notUploadFiles.Add(file.Name);
}
}
if(notUploadFiles is not null) {
Snackbar.Configuration.SnackbarVariant = Variant.Filled;
Snackbar.Add("The following files could not be uploaded:", Severity.Info);
Snackbar.Configuration.SnackbarVariant = Variant.Outlined;
foreach (var file in notUploadFiles)
{
Snackbar.Add(file, Severity.Error);
}
//Snackbar.Configuration.PositionClass = Defaults.Classes.Position.TopCenter;
//Snackbar.Add("TODO: Upload your files!", Severity.Normal);
MudDialog.Close(DialogResult.Ok(true));
}
Snackbar.Add("All files have been successfully uploaded", Severity.Success);
MudDialog.Close(DialogResult.Ok(true));
}
I don't know where is the problem, any idea?
The uploaded files are not in the file system, they are in-memory only. The way to access the raw data would be something like:
byte[] fileBytes;
using (Stream s = file.OpenReadStream())
{
MemoryStream ms = new MemoryStream();
await s.CopyToAsync(ms);
fileBytes= ms.ToArray();
}

How to Backup all the folders and files in a USB using UWP C#?

In my program, I will need to have a method that are able to backup the whole USB drive to a desired location folder. Just like how we are able to copy the whole folders and files in the USB, but with just a click on my program.
Currently I am only able to backup a single folder with just files in it. Please advise.
Thank you.
public async Task CopyFolderAsync(string targetFolder, string desiredName)
{
StorageFolder externalDevices = KnownFolders.RemovableDevices;
IReadOnlyList<StorageFolder> externalDrives = await externalDevices.GetFoldersAsync();
StorageFolder rootFolder = externalDrives[0];
StorageFolder source = await rootFolder.GetFolderAsync(targetFolder);
StorageFolder destinationFolder = await rootFolder.CreateFolderAsync(desiredName, CreationCollisionOption.GenerateUniqueName);
foreach (var file in await source.GetFilesAsync())
{
await file.CopyAsync(destinationFolder, file.Name, NameCollisionOption.ReplaceExisting);
}
await _logManager.GenerateLog("Copying Done");
}
You could use the following code to copy all the folders and files in a certain folder:
public static async Task CopyFolderAsync(StorageFolder source, StorageFolder destinationContainer, string desiredName = null)
{
StorageFolder destinationFolder = null;
destinationFolder = await destinationContainer.CreateFolderAsync(
desiredName ?? source.Name, CreationCollisionOption.ReplaceExisting);
foreach (var file in await source.GetFilesAsync())
{
await file.CopyAsync(destinationFolder, file.Name, NameCollisionOption.ReplaceExisting);
}
foreach (var folder in await source.GetFoldersAsync())
{
await CopyFolderAsync(folder, destinationFolder);
}
}
public async Task CopyFolderAsync(string targetFolder, string desiredName)
{
……
//Get the rootFolder and destinationFolder
await CopyFolderAsync(rootFolder, destinationFolder);
}

Xamarin.forms ImageSource.FromFile doesn't work

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;

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