How to render media compostion to existing file - c#

I want to edit a video file with UWP media composition and then save it back to the existing file. However, when I select the same file the rendering doesn't work because the data stream get corrupt.
As a workaround I render the video to a temporary file and move it then to the existing location:
// Create temp file
var tempFolder = ApplicationData.Current.TemporaryFolder;
StorageFile tempFile = await tempFolder.CreateFileAsync(Guid.NewGuid().ToString(), CreationCollisionOption.ReplaceExisting);
// Render video to temp file so stream get not corrupted
mediaComposition.RenderToFileAsync(tempFile, MediaTrimmingPreference.Precise);
// If rendering completed move temp file to existing video
await tempFile.MoveAndReplaceAsync(existingFile);
My workaround works fine except that the temporary folder is on my local disk and when I edit large video files on my external disk I can run out of storage on my local disk.
Is there another possibility to override an existing file with RenderToFileAsync()?
Update:
As suggested in the comments I set the file size to zero with the following code but then I get a FileNotFoundException:
var stream = await file.OpenAsync(FileAccessMode.ReadWrite);
stream.Size = 0;
stream.Dispose();

Related

C# - Extracting contents of compressed file without saving

I have a compressed file (.osz) stored on an S3 Bucket which contains a .os file which I need to read the contents of.
I need to be able to extract/decompress and read the contents of the compressed file without downloading the file directly to the PC due to security reasons.
I am able to retrieve the compressed file (.osz) using the URL address of it's S3 Bucket path. Then using ZipArchive I am able to access the files contained within the compressed file. I am then able to extract the file I require by using the 'ExtractToFile' function as seen below. However, this function extracts the file (.os) and saves it locally in the path specified.
WebClient client = new WebClient();
byte[] bytes = client.DownloadData(OSZFilepath); // Read the .osz file contents into a byte array
using (MemoryStream zipStream = new MemoryStream(bytes))
{
// Create the zip containing the file from the stream
ZipArchive zip = new ZipArchive(zipStream);
// extract the compressed file and download the .os file contained within
var fileName = Guid.NewGuid().ToString() + ".OS";
var baseDirectory = Environment.ExpandEnvironmentVariables(System.Web.Configuration.WebConfigurationManager.AppSettings["DataStorage"].ToString());
zip.Entries[0].ExtractToFile(Path.Combine(baseDirectory, "ProjectFiles", fileName));
Although this extracted file can be successfully read and imported by my program, I cannot use this method as I am not able to save the file onto the user's computer due to security restrictions and program requirements.
Therefore I need to programmatically extract/decompress the file I need in order to read the contents and programmatically import it into my program.
I have tried to use the following code to do this:
ZipArchiveEntry entry = zip.GetEntry(zip.Entries[0].Name);
Stream stream = entry.Open();
StreamReader reader = new StreamReader(stream);
string contents = reader.ReadToEnd();
However the resulting contents throws up an error when I try to import it, indicating that the contents is different to the contents of the file that gets saved using 'ExtractToFile'.
This is confirmed when I save this contents as a seperate file and compare it to the file saved using 'ExtractToFile'. The 'ExtractToFile' file is bigger than the latter.
So my question is: is there another way to successfully decompress/extract a compressed file and obtain the contents without using the 'ExtractToFile' method and having to save the extracted file somewhere?
Thanks for your help.

How to upload an audio file with ID3 tags into an application using C# and visual studio

I am currently working on code to pull an mp3 file from a user's computer and upload it into a music library application that I am creating in visual studio UWP using C#. It needs to be able to pull the ID3 tags for artist, title, and album, as these will all have to be referenced on the actual library page, where the music will be sorted accordingly.
The following code is what I have so far, and I am currently stuck on what else to write just to upload the file into the music library portion of my app with the ID3 tags:
//Uploading Music File Button
private async void UploadButton_Click(object sender, RoutedEventArgs e)
{
//Opening User's personal Music Library to select files
var picker = new Windows.Storage.Pickers.FileOpenPicker
{
ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail,
SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.MusicLibrary
};
//Accepted file type = mp3 (only mp3 files display for user selection)
picker.FileTypeFilter.Add(".mp3");
StorageFile file = await picker.PickSingleFileAsync();
if (file != null)
{
// Application now has read/write access to the picked file
//Storing File for future use
Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.Add(file);
// Open a stream for the selected file.
// The 'using' block ensures the stream is disposed
// after the music is loaded.
IRandomAccessStream fileStream =
await file.OpenAsync(FileAccessMode.ReadWrite);
}
}
I am very new to all this, so I may be missing some very obvious things in this code. I have checked into various tutorials and examples, but none of them provide the exact fit I'm looking for or are half done. Thank you for taking the time to read my code and offer any advice/suggestions.
How to upload an audio file with ID3 tags into an application using C# and visual studio
For accessing audio metadata, you could use GetMusicPropertiesAsync method to get audio file's album artist title MusicProperties property.
try
{
StorageFile file = rootPage.sampleFile;
if (file != null)
{
StringBuilder outputText = new StringBuilder();
// Get music properties
MusicProperties musicProperties = await file.Properties.GetMusicPropertiesAsync();
outputText.AppendLine("Album: " + musicProperties.Album);
outputText.AppendLine("Rating: " + musicProperties.Rating);
}
}
// Handle errors with catch blocks
catch (FileNotFoundException)
{
// For example, handle a file not found error
}
For uploading the audio file to server, you could use BackgroundTransfer api. and this is code sample you could refer to. And you could also you HttpClient API to post your file stream.

Save changes in file in Windows Store app in required directory

using c#, VS2013, windows store app
In simple program have a file with some data saved in JSON format. I'll try to add new data to this file and then store it.
Try to save file in JSON with next code:
string result = await JsonConvert.SerializeObjectAsync(groups);
//get file path
string pathOfFile = Path.GetDirectoryName(file.Path); //get path
StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(pathOfFile); //create dir by path
StringBuilder builder = new StringBuilder();
builder.Append(folder.Path);
builder.Append("\\EventsData.json");
Uri uriToSave = new Uri(builder.ToString());
//create file
StorageFile fileToWrite =
await StorageFile.GetFileFromApplicationUriAsync(uriToSave);
using (IRandomAccessStream stream =
await file.OpenAsync(FileAccessMode.ReadWrite))
{
// write the JSON file
using (DataWriter textWriter = new DataWriter(stream))
{
textWriter.WriteString(result);
await textWriter.StoreAsync();
}
}
But during executing code StorageFile fileToWrite = await StorageFile.GetFileFromApplicationUriAsync(uriToSave); got exception System.ArgumentException
During debagging got next Uri
Question - why i got such exception and if I'm wrong - how to save file in windows store app in required directory?
Also look MSDN sample for writing data to file, and use code like in tutorial but got System.UnauthorizedAccessException:
StorageFile sampleFile = await folder.CreateFileAsync("EventsData.json", CreationCollisionOption.ReplaceExisting);
await Windows.Storage.FileIO.WriteTextAsync(sampleFile, result);
Why Access denied or I missing something?
You cannot write to the install directory without explicit permission from the user.
Here is the protocol instead:
At first startup, check to see if there is a file in the local data folder (ApplicationDataContainer), if not, read in the file from the install directory.
Write out a copy of the file to the local app data folder (Check out guides on ApplicationDataContainer for more info there)
Edit this file freely.

Generating a zipOutputstream from a folder having other .zip files in it

I am trying to convert an entire azure blob storage folder and its contents to a zip file .Inside this folder ,I have different types of files eg, .txt,.mp3,.zip files .But once the folder is converted to zip file I noticed that all the .zip file types got corrupted,.How can I prevent my zip files from corrupted. I am using Ionic.Zip library to generate zip files
Here is the code I am using .Here I am able to generate and download the zip file successfully with all other filetypes except the inner zip files.
var allFiles = directory.ListBlobs(new BlobRequestOptions { UseFlatBlobListing = true }).Where(x => x.GetType() == typeof(CloudBlockBlob)).Cast<CloudBlob>();
string xyzblob = directory.Uri.ToString().TrimEnd('/');
var dBlob = blobClient.GetBlobReference(xyzblob);
byte[] fileBytes = null;
fileBytes = dBlob.DownloadByteArray();
foreach (var file in allFiles)
{
using (var fileStream = new MemoryStream(fileBytes))
{
var entryName = file.Uri.ToString().Replace(directory.Uri.ToString(), "");
zipOutputStream.PutNextEntry(entryName);
fileStream.Seek(0, SeekOrigin.Begin);
int count = fileStream.Read(fileBytes, 0, fileBytes.Length);
while (count > 0)
{
zipOutputStream.Write(fileBytes, 0, count);
count = fileStream.Read(fileBytes, 0, fileBytes.Length);
if (!Response.IsClientConnected)
{
break;
}
Response.Flush();
}
fileStream.Close();
}
}
zipOutputStream.Close();
More details
I am downloading a folder ,."myFolder" and its contents from azure blob as a zip file eg, myfolders.zip.
Here is how the file structure inside "myFolder" /azure blob
MyFolder/mymusic/ test.mp3
MyFolder/mytext/ newtext.txt
MyFolder/MyZipfiles/ myzip.zip
My code I posted above will generate a zip all the contents of the folder to create "MyFolder.zip" and will download automatically .Now if you unzip "MyFolder.zip" file , due to some reason , the myzip.zip is getting corrupted.If I try to open myzip.zip file ,its showing a message "windows cannot open the folder ,the compressed zipped folder "myzip.zip" is invalid"
Please help me find a solution so that the .zip files wont get corrupted
I tried to download to stream ,but same results.,The inner zip files are getting corrupted.all other file types are in good shape.
zipOutputStream.PutNextEntry(entryName);
destBlob.DownloadToStream(zipOutputStream);
I am assuming you already tried downloading one of those zip files and opening it, right?
If that is the case, one thing I would suggest is to eliminate the intermediate fileBytes array completely. Using fileBytes as the buffer to fileStream and then reading from fileStream to fileBytes might be the culprit. On the other hand, you start from offset 0 and write to the beginning of fileBytes anyway, so it might be working just fine.
In any case, a more efficient solution is; you can call PutNextEntry and then call the blob object's DownloadToStream method by passing in the zip stream itself. That would simply copy the entire blob directly into the zip stream without having to manage an intermediate buffer.
When it starts to pick the .zip file ,I added BlobReference to .zip file and this resolved the issue
dBlob = blobClient.GetBlobReference(entryName.EndsWith(".zip") ? file.Uri.ToString() : xyzblob);
zipOutputStream.PutNextEntry(entryName);
dBlob.DownloadToStream(zipOutputStream);

File.Move locks file in destination folder?

I use File.Move to move large files around 2GB from a directory to another directory.The desitnation folder is monitored and if there is any new file, it will be uploaded to CDN. But we experienced some partial file upload to CDN which means, the respective file was uploaded to CDN while the same file was moving from source to destination directory. So, I need to know whether File.Move locks the file destination folder till the file is completed moved?
What you can do to avoid partial upload to CDN is to hide it first when moving it and unhide it once it's completely done. And have the monitoring tool not transfer it to the CDN if the file is still hidden.
Or you can lock it out so that other processes (which is your monitoring tool -- CuteFTP) can't access the destination file until the stream is already finished.
e.g.
static void Main(string[] args)
{
string sourcePath = "mytext.txt";
string destPath = #"dest\mytext.txt";
using (FileStream sourceStream = new FileStream(sourcePath, FileMode.Open))
{
using (FileStream destStream = new FileStream(destPath, FileMode.Create))
{
destStream.Lock(0, sourceStream.Length);
sourceStream.CopyTo(destStream);
}
}
if (File.Exists(sourcePath))
{
File.Delete(sourcePath);
}
}
Your problem is the moonitoring on the destination folder.
Since you have a big file, it take time to copy it so what happend is :
You start moving the file
Monitoring system kick in and start uploading to CDN
File was parialy uploaded
You finish moving the file.
One mitigation for this is , assuming your monitoring system searching for files with some extensation - moving MyBigFile.ext to MyBigFile.ext.tmp. after finish , rename it back to MyBigFile.ext, so when monitoring kick in , it will have the complete file

Categories

Resources