Retrieving recorded media (videos/photos) - c#

I'm having trouble retrieving videos that I have recorded from my app on my iPhone.
The purpose of this is to upload this recorded video to Amazon Web Service's cloud (store it in a bucket).
However I seem to only be have directory access capabilities instead of the actual files. I don't know if this is a permissions issue or if there's a specific class that allows me to retrieve recorded videos.
This snippet of code saves the video:
var options = new PHAssetResourceCreationOptions {};
var changeRequest = PHAssetCreationRequest.CreationRequestForAsset ();
changeRequest.AddResource (PHAssetResourceType.Video, outputFileUrl, options);
The path from the outputFileUrl, which saves to the iPhone's temp folder, is how I was going about trying to retrieve the file to upload but to no success.
Can someone help me with this?
I have an toggle Record Event that gets the file like this:
// Start recording to a temporary file.
MovieFileOutput.StartRecordingToOutputFile (new NSUrl(GetTmpFilePath ("mov"), false), this);
This is the definition for GetTmpFilePath():
static string GetTmpFilePath (string extension)
{
// Start recording to a temporary file.
string outputFileName = NSProcessInfo.ProcessInfo.GloballyUniqueString;
string tmpDir = Path.GetTempPath();
string outputFilePath = Path.Combine (tmpDir, outputFileName);
return Path.ChangeExtension (outputFilePath, extension);
}
outputFileUrl is a NSUrl and is the result of this, it is a parameter to the method that uses this in the "AddResource" above.

Related

Store and read csv file from android and ios in Unity

I have a Unity project which I want to work for both android and ios. I also have a csv file which I want to read during runtime. I tried the following code:
string basePath = Path.Combine(Application.persistentDataPath, $"{fileName}.csv");
if (File.Exists(basePath))
{
string[] rows = File.ReadAllLines(basePath);
foreach (string item in rows)
{
Debug.Log(item);
}
}
However, I don't know where to put the csv file for it to find it on persistentDataPath. And if I find the correct place, will it be the same on android and ios or do I need to save the file on more locations or folders?
Or do you have any other suggestions on how to store and then load a cvs for different platforms?
If you just want to read a .csv file that you deploy with your game, you could just place it into the Resources folders inside your Assets.
You could read it like this:
TextAsset file = Resources.Load(fileName) as TextAsset;
string content = file.ToString();
Note: fileName must be specified here without file extension.
If you want to modify the .csv file or perhaps make it available in Application.persistentDataPath, you can simply copy it to that location first. For later changes you can then access the file in persistentDataPath.
Self-Contained Example
A self-contained example could look something like this:
using System.IO;
using UnityEngine;
public class CSVFileManager : MonoBehaviour
{
void Start()
{
var fileName = "example";
var csvFileName = $"{fileName}.csv";
string basePath = Path.Combine(Application.persistentDataPath, csvFileName);
Debug.Log($"basePath = >>{basePath}<<");
if (!File.Exists(basePath))
{
TextAsset file = Resources.Load(fileName) as TextAsset;
string content = file.ToString();
File.WriteAllText(basePath, content);
}
else
{
//... work with the current file in persistentDataPath
}
}
}
Test
I tested it briefly on Mac, but it should work equally well on Android and iOS:

Why is my zip file not showing any contents?

I've created a zip file method in my web api which returns a zip file to the front end (Angular / typescript) that should download a zip file in the browser. The issue I have is the file shows it has data by the number of kbs it has but on trying to extract the files it says it's empty. From a bit of research this is most likely down to the file being corrupt, but I want to know where I can find this is going wrong. Here's my code:
WebApi:
I won't show the controller as it basically just takes the inputs and passes them to the method. The DownloadFileResults passed in basically have a byte[] in the File property.
public FileContentResult CreateZipFile(IEnumerable<DownloadFileResult> files)
{
using (var compressedFileStream = new MemoryStream())
{
using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Update))
{
foreach (var file in files)
{
var zipEntry = zipArchive.CreateEntry(file.FileName);
using (var entryStream = zipEntry.Open())
{
entryStream.Write(file.File, 0, file.File.Length);
}
}
}
return new FileContentResult(compressedFileStream.ToArray(), "application/zip");
}
}
This appears to work in that it generates a result with data. Here's my front end code:
let fileData = this._filePaths;
this._fileStorageProxy.downloadFile(Object.entries(fileData).map(([key, val]) => val), this._pId).subscribe(result => {
let data = result.data.fileContents;
const blob = new Blob([data], {
type: 'application/zip'
});
const url = window.URL.createObjectURL(blob);
window.open(url);
});
The front end code then displays me a zip file being downloaded, which as I say appears to have data due to it's size, but I can't extract it.
Update
I tried writing the compressedFileStream to a file on my local and I can see that it creates a zip file and I can extract the files within it. This leads me to believe it's something wrong with the front end, or at least with what the front end code is receiving.
2nd Update
Ok, turns out this is specific to how we do things here. The request goes through platform, but for downloads it can only handle a BinaryTransferObject and I needed to hit a different end point. So with a tweak to no longer returning a FileContentResult and hitting the right end point and making the url simply an ahref it's now working.

azure blob download via SAS

All,
I have a blob container with nested filenames (simulating a folder).
Is it possible to download via code (bypassing the webserver) through SAS URI for a bunch of files beginning with a prefix?
Right now, i am zipping these files and sending it to a stream below..
CloudBlobContainer container = GetRootContainer();
CloudBlockBlob caseBlob = container.GetBlockBlobReference(folderPrefix);
await caseBlob.DownloadToStreamAsync(zipStream);
This works and i can download the set of files beginning with that prefix to a client machine. However this is dependent on the webserver's speed and its comparatively slow.
Is there an example on how to download using SAS by providing a URI for the folder? Here is an example i found from another post in stackoverflow
var sasConstraints = new SharedAccessBlobPolicy();
sasConstraints.SharedAccessStartTime = DateTime.UtcNow.AddMinutes(-5);
sasConstraints.SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(10);
sasConstraints.Permissions = SharedAccessBlobPermissions.Read;
var sasBlobToken = blob.GetSharedAccessSignature(sasConstraints);
return blob.Uri + sasBlobToken;
//Here can the URI point to the prefix??
Can i use something like this?
Thanks!
It is certainly doable however it won't be a single step process.
First, you can't have a SAS Token for a virtual folder. You will need to get a SAS token for the blob container with both List (for listing blobs) and Read (for downloading blob) permissions.
Next you will list the blobs in the virtual folder inside the blob container. In order to do so, you will need to specify the virtual folder path as the prefix. This will give you a list of blobs inside that virtual folder. Please ensure that you specify empty string as delimiter so that all blobs inside that virtual folders are listed.
Once you have the list of blobs, you will need to read (download) the blobs and store the blob content somewhere in the browser.
After you have read the blob contents, you could use a JS based zip library to dynamically create zip file contents and once all the blobs are added to the zip file, you can force download of that zip file. A quick search for JS based zip library landed me here: https://stuk.github.io/jszip/. When I implemented this functionality in a product I built, I used ZipJS library but unfortunately I am not able to find it online though now.
Bits and pieces of the code I wrote many years ago (it was part of a much larger application + there was no JS Storage SDK when I wrote it so apologies if the code does not much sense to you. Please use it for general guidance only).
zip.workerScriptsPath = '/Scripts/ZipJS/';
zipWriter = new zip.BlobWriter();
zip.createWriter(zipWriter, function (zipWriter) {
startZippingFiles(zipWriter);
}, function () {
}, true);
function startZippingFiles(writer) {
if (downloadedContent.length > 0) {//downloadedContent is an array containing downloaded blobs
var downloadedContentItem = downloadedContent.shift();//read first item
var cloudBlob = downloadedContentItem.Blob;//get the cloud blob object
var blobContents = downloadedContentItem.Content;//get the blob's content
var status = downloadedContentItem.Status;//status to track blob's download status
if (status === 'Completed') {
writer.add(cloudBlob.name,
new zip.BlobReader(new Blob([blobContents], { type: cloudBlob.properties.contentType })), function () {
console.log(cloudBlob.name + ' added to zip...')
downloadedBlobsCount += 1;
startZippingFiles(writer);
}, function (o) {
console.log('Adding ' + cloudBlob.name + ' to zip file. ' + parseFloat((o * 100) / cloudBlob.size).toFixed(2) + '% done...');
});
}
} else {
writer.close(function (blob) {//Finally save the zipped data as download.zip
saveAs(blob, "download.zip");
zipWriter = null;
});
console.log("Download successful!");
}
}

MediaSource.CreateFromUri(...) cannot retrieve the file for MediaSource.

Here is my code........
public MediaPlaybackItem GetMediaPlaybackItemFromPath(string path)
{
//StorageFile file = await StorageFile.GetFileFromPathAsync(path);
var source = MediaSource.CreateFromUri(new Uri(path));
return new MediaPlaybackItem(source);
}
If I use this method I cannot play music. But if I try this I can play music.
public async Task<MediaPlaybackItem> GetMediaPlaybackItemFromPathAsync(string path)
{
StorageFile file = await StorageFile.GetFileFromPathAsync(path);
var source = MediaSource.CreateFromStorageFile(file);
return new MediaPlaybackItem(source);
}
Whats the problem with this? I am using mediaplaybacklist for MediaPlayer.Source . How can I get proper MediaSource using my first method? Help me please.
You could not pass file path parameter to CreateFromUri directly. In general, the Uri parameter is http protocol address such as http://www.testvideo.com/forkvideo/test.mp4. But we could pass the file path with uwp file access uri scheme.
For example:
Media file stored in the installation folder.
ms-appx:///
Local folder.
ms-appdata:///local/
Temporary folder.
ms-appdata:///temp/
For more you could refer this document.

Getting song meta data

I'm trying to get the metadata from an absolute URL to a song, such as http://www.<url>.com/<file>.mp3
How do I go about doing this. I'm a little new to the C# api's so I'm a little lost in terms of what classes to use.
I found this block of code from searching around:
StorageFile newFile = //file
var prop =await newFile.Properties.GetMusicPropertiesAsync();
string album = prop.Album;
and I was wondering what goes in the //file field? What class is of type StorageFile that will take in a URI?
Thank you.
First, you can download the mp3 file to local using this:
WebClient Client = new WebClient ();
Client.DownloadFile("http://myserver.com/indie/band1.mp3", "band1.mp3");
Then, use TagLibSharp https://github.com/mono/taglib-sharp
//Local reference to the file
TagLib.File file = TagLib.File.Create("band1.mp3");
//Get the file metadata
Console.WriteLine("Tags on disk: " + file.TagTypesOnDisk);
Console.WriteLine("Tags in object: " + file.TagTypes);
Write ("Grouping", file.Tag.Grouping);
Write ("Title", file.Tag.Title);
Write ("Album Artists", file.Tag.AlbumArtists);
Write ("Performers", file.Tag.Performers);
Write ("Composers", file.Tag.Composers);
Write ("Conductor", file.Tag.Conductor);
Write ("Album", file.Tag.Album);
Write ("Genres", file.Tag.Genres);
Write ("BPM", file.Tag.BeatsPerMinute);
Write ("Year", file.Tag.Year);
Write ("Track", file.Tag.Track);
Write ("TrackCount", file.Tag.TrackCount);
Write ("Disc", file.Tag.Disc);
Write ("DiscCount", file.Tag.DiscCount);

Categories