Xamarin C# Android - converting .3gpp audio to bytes & sending to parseObject - c#

I'm pretty new to processing recorded sound.
I can successfully record audio into a .3gpp file, save it locally on my mobile device, and play it back.
The trouble I'm having is that I want to convert the sound file into binary so that I can stick it into a parseObject, and upload the file to a cloud. I then want to be able to access that file from a separate device, and stream it.
--UPDATE--- I'm not using binary anymore, I'm using a parseFile object. I now just need to pull the object down from the cloud.
Here's the code I'm using to record the audio (working):
string sName;
string path = "/storage/extSdCard/";
string newPath = "";
_start.Click += delegate {
_stop.Enabled = !_stop.Enabled;
_start.Enabled = !_start.Enabled;
sName = _edittext.Text;
if (sName.Equals(" "))
{
}
else
{
//user enters a name for ther audio file
newPath = path + sName + ".3gpp";
_recorder.SetAudioSource (AudioSource.Mic);
_recorder.SetOutputFormat (OutputFormat.ThreeGpp);
_recorder.SetAudioEncoder (AudioEncoder.AmrNb);
_recorder.SetOutputFile (newPath);
_recorder.Prepare ();
_recorder.Start ();
}
};
_stop.Click += delegate {
_stop.Enabled = !_stop.Enabled;
_recorder.Stop ();
// _recorder.Reset ();
_player.SetDataSource (newPath);
_player.Prepare ();
_player.Start ();
};
Here is the class I'm using to send the data to a cloud - this is executed on the click of a button and works, it currently sends hard coded strings into an object which i can successfully retrieve.
HOWEVER, I want the binary string to go into the testObject["audio"], so I can retrieve it.
async Task sendToCloud()
{
ParseClient.Initialize ("--I've put my keys here but I'm censoring them--", "--I've put my keys here but I'm censoring them--");
try
{
byte[] data =null;
ParseFile file = null;
using (StreamReader reader = new StreamReader(LoadPath))
{
data = System.Text.Encoding.UTF8.GetBytes(reader.ReadToEnd());
file = new ParseFile("theaudio.3gpp", data);
}
Console.WriteLine("Awaiting reader");
await file.SaveAsync ();
var auidoParseObject = new ParseObject("AudioWithData");
//Console.WriteLine(ParseUser.getUserName());
auidoParseObject["userName"] = "userName";
auidoParseObject["file"] = file;
await auidoParseObject.SaveAsync();
}
Any help would be GREATLY APPRECIATED.
EDIT2:
I've made some progress, I'm struggling, however, to get the audio file down from the cloud still.
here's my new code:
async Task sendToCloud(string filename)
{
ParseClient.Initialize ("censored", "censored");
var testObject = new ParseObject ("Audio");
string LoadPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
string savetheFile = sName + ".3gpp";
string tempUserName;
LoadPath += savetheFile;
Console.WriteLine ("loadPath: " + LoadPath);
try
{
byte[] data = File.ReadAllBytes(LoadPath);
ParseFile file = new ParseFile(savetheFile, data);
await file.SaveAsync();
var auidoParseObject = new ParseObject("AudioWithData");
//Console.WriteLine(ParseUser.getUserName());
if (ParseUser.CurrentUser != null)
{
tempUserName = ParseUser.CurrentUser.Username.ToString();
}
else{
tempUserName = "Anonymous";
}
//tempUserName = ParseUser.CurrentUser.Username.ToString();
Console.WriteLine("PARSE USERNAME: " + tempUserName);
auidoParseObject["userName"] = tempUserName;
auidoParseObject["userName"] = tempUserName;
auidoParseObject["file"] = file;
await auidoParseObject.SaveAsync();
}
catch (Exception e)
{
Console.WriteLine("Failed to await audio object! {0}" + e);
}
}
So currently, my objects have the following structure:
"auidoParseObject" contains two children: username (string) and file (ParseFile object)
"file" has two children: the name of the audio (entered by the user -string), and the data in bytes.
I need the audio to be placed into a mdeiaplayer player object, and played.
In the long run, I'll want to extract:
(forgive my pseudo-SQL, but I don't understand the querying documentation):
Select (all files) from (audioParseObject) where (the username = current user.username)
AND THEN
put those files into a listview
user selects a file from the listview and it plays.
ANY help or pointers would be great.
Thanks.

Parse has really good docs on their site with examples - have you read them?
First, you would use a ParseFile (not a ParseObject) to save your file
byte[] data = File.ReadAllBytes(path_to_your_file);
ParseFile file = new ParseFile("your_file_name_and_ext", data);
await file.SaveAsync();
After you save your file, you can add a reference to it in your ParseObject
testObject ["audio"] = file;
To retrieve the file later, you use the Url property from the ParseFile.
var file = testObject.Get<ParseFile>("audio");
byte[] data = await new HttpClient().GetByteArrayAsync(file.Url);

Related

How to upload an IFormFile with MS Graph SDK

I have put together the following function to upload a file from the web server to OneDrive with MS Graph. However, I am no longer saving files to the server and would rather just take the IFormFile from my users form submit and then upload that straight to OneDrive. However, my function uses a path on the web server. How do I convert this to use IformFile directly without saving it to a physical server path?
public async Task<String> UploadFileAsync(string DriveID, string SourceFile, string DestinationPath)
{
try
{
using var fileStream = System.IO.File.OpenRead(SourceFile);
// Use properties to specify the conflict behavior
// in this case, replace
var uploadProps = new DriveItemUploadableProperties
{
AdditionalData = new Dictionary<string, object>
{
{ "#microsoft.graph.conflictBehavior", "fail" }
}
};
// Create the upload session
// itemPath does not need to be a path to an existing item
var uploadSession = await _graphServiceClient.Me.Drives[DriveID].Root
.ItemWithPath(DestinationPath)
.CreateUploadSession(uploadProps)
.Request()
.PostAsync();
// Max slice size must be a multiple of 320 KiB
int maxSliceSize = 320 * 1024;
var fileUploadTask =
new LargeFileUploadTask<DriveItem>(uploadSession, fileStream, maxSliceSize);
var totalLength = fileStream.Length;
// Create a callback that is invoked after each slice is uploaded
IProgress<long> progress = new Progress<long>(prog => {
Console.WriteLine($"Uploaded {prog} bytes of {totalLength} bytes");
});
// Upload the file
var uploadResult = await fileUploadTask.UploadAsync(progress);
Console.WriteLine(uploadResult.UploadSucceeded ?
$"Upload complete, item ID: {uploadResult.ItemResponse.Id}" :
"Upload failed");
return uploadResult.ItemResponse.Id;
}
catch (ServiceException ex)
{
Console.WriteLine($"Error uploading: {ex.ToString()}");
return "Failed: " + ex.ToString();
}
}
This creates the file no problem and returns the

How to upload files to one drive from .NET

I need to maintain a historical record of certain documents, my initial solution was to copy them to a shared folder from .NET, but that doesn't seem so safe to me. Can I make the upload of those files to One Drive by using .NET with C#? If so, I would like documentation about it, I've already done a free search and I haven't found anything that could satisfy my needs. I apologize if the question is way too vague. Thank you.
Maybe this can help you out:
Using the code:
public string OneDriveApiRoot { get; set; } = "https://api.onedrive.com/v1.0/";
Upload file to OneDrive
//this is main method of upload file to OneDrive
public async Task<string> UploadFileAsync(string filePath, string oneDrivePath)
{
//get the upload session,we can use this session to upload file resume from break point
string uploadUri = await GetUploadSession(oneDrivePath);
//when file upload is not finish, the result is upload progress,
//When file upload is finish, the result is the file information.
string result = string.Empty;
using (FileStream stream = File.OpenRead(filePath))
{
long position = 0;
long totalLength = stream.Length;
int length = 10 * 1024 * 1024;
//In one time, we just upload a part of file
//When all file part is uploaded, break out in this loop
while (true)
{
//Read a file part
byte[] bytes = await ReadFileFragmentAsync(stream, position, length);
//check if arrive file end, when yes, break out with this loop
if (position >= totalLength)
{
break;
}
//Upload the file part
result = await UploadFileFragmentAsync(bytes, uploadUri, position, totalLength);
position += bytes.Length;
}
}
return result;
}
private async Task<string> GetUploadSession(string oneDriveFilePath)
{
var uploadSession = await AuthRequestToStringAsync(
uri: $"{OneDriveApiRoot}drive/root:/{oneDriveFilePath}:/upload.createSession",
httpMethod: HTTPMethod.Post,
contentType: "application/x-www-form-urlencoded");
JObject jo = JObject.Parse(uploadSession);
return jo.SelectToken("uploadUrl").Value<string>();
}
private async Task<string> UploadFileFragmentAsync(byte[] datas, string uploadUri, long position, long totalLength)
{
var request = await InitAuthRequest(uploadUri, HTTPMethod.Put, datas, null);
request.Request.Headers.Add("Content-Range", $"bytes {position}-{position + datas.Length - 1}/{totalLength}");
return await request.GetResponseStringAsync();
}
Get Share Link: ( Javascript )
//This method use to get ShareLink, you can use the link in web or client terminal
public async Task<string> GetShareLinkAsync(string fileID, OneDriveShareLinkType type, OneDrevShareScopeType scope)
{
string param = "{type:'" + type + "',scope:'" + scope + "'}";
string result = await AuthRequestToStringAsync(
uri: $"{OneDriveApiRoot}drive/items/{fileID}/action.createLink",
httpMethod: HTTPMethod.Post,
data: Encoding.UTF8.GetBytes(param),
contentType: "application/json");
return JObject.Parse(result).SelectToken("link.webUrl").Value<string>();
}
From: https://code.msdn.microsoft.com/office/How-to-upload-file-to-21125137
An easy solution for beginners:
Install OneDrive app on your computer then login to your account and set a folder to it.
Then you just need to copy your files in the folder you set in the last step. It would be synced automatically by OneDrive application.
File.Copy(sourceFileFullPath,OneDriveFileFullPath);

How to read and write from file in C# UWA (Universal Windows App)

I am trying to figure out how to read and write files in a UWA application. I understand that I need to open a FileStreamm, but I can't figure out how to do that.
I started with this code:
FileStream fs = new FileStream(#"C:\XML\test.txt", FileMode.Create, FileAccess.Write);
seems to work, no red lines.
At the end of all of that I am told to put in Flush and Close, like this:
FileStream fs = new FileStream(#"C:\XML\test.txt", FileMode.Create,
...
fs.Flush();
fs.Close();
Now, this is where I hit a snag, because fs.Close(); is not even on the list of functions on fs. I just get a red line in my IDE if I try to hardcode it.
Can someone please take the time to help me understand how to do this with UWA? For some reason it seems like there is a different approach in Windows 10 apps, and I have a VERY hard time finding anything that shows me how to do it right. All the tutorials and SOF forum input are about older versions (non-UWA).
When I do this in a console application it all works as expected.
My end goal is to be able to read and write to an XML file in this kind of fashion:
XDocument doc = XDocument.Load(input);
XElement person = doc.Element("Person");
person.Add(new XElement("Employee",
new XElement("Name", "David"),
new XElement("Dept", "Chef")));
doc.Save(output);
I'm going down this path because an answer to my previous question told me to use a FileStream, but I simply cannot make that work in UWA.
You cannot just access any file from a Universal Windows App. Access to the file system is restricted.
See the documentation for details.
To help you further we need to know more about your application. What kind of files do you want to access for what reason?
Example on how to read an Xml File, modify it and store it in an Universal app. You need a button with the following Click handler and a TextBox named "TextBoxLog".
private async void ButtonDemo_Click(object sender, RoutedEventArgs e)
{
// Get our local storage folder
var localFolder = ApplicationData.Current.LocalFolder;
XmlDocument xmlDocument;
// Try to get file
var file = await localFolder.TryGetItemAsync("MyData.xml") as IStorageFile;
if(file != null)
{
// File exists -> Load into XML document
xmlDocument = await XmlDocument.LoadFromFileAsync(file);
}
else
{
// File does not exist, create new document in memory
xmlDocument = new XmlDocument();
xmlDocument.LoadXml(#"<?xml version=""1.0"" encoding=""UTF-8""?>" + Environment.NewLine + "<root></root>");
}
// Now show the current contents
TextBoxLog.Text = "";
var lEntries = xmlDocument.GetElementsByTagName("Entry");
foreach(var lEntry in lEntries)
{
TextBoxLog.Text += lEntry.InnerText + Environment.NewLine;
}
// Now add a new entry
var node = xmlDocument.CreateElement("Entry");
node.InnerText = DateTime.Now.ToString();
xmlDocument.DocumentElement.AppendChild(node);
// If the file does not exist yet, create it
if(file == null)
{
file = await localFolder.CreateFileAsync("MyData.xml");
}
// Now save the document
await xmlDocument.SaveToFileAsync(file);
}
Okay, the (simple) solution is to put the xml-file in the PROJECTFOLDER/bin/x86/debug/appX and then write the data to a list this way:
public class dataRaw
{
public string data { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
}
//You can call this class with x = collectionGenerator.getList() (it returns a list<T>)
public class collectionGenerator
{
public static List<dataRaw> getList()
{
//This is the xml file in the folder
var doc = XDocument.Load("Data.xml");
//This parse the XML and adds in to the list "dataList"
var dataList = doc.Root
.Descendants("Person")
.Select(node => new dataRaw
{
//data, firstName and lastName are in app variables from dataRaw put into listData.
//Number, FirstName and LastName are the nodes in the XML file.
data = node.Element("Number").Value,
firstName = node.Element("FirstName").Value,
lastName = node.Element("LastName").Value,
})
.ToList();
return dataList;
}
}

C# Drag and Drop attached file from outlook email

I want to use/read attached files from an outlook email into a WinForm solution.
Ex: the email has a TXT file attached; I want to perform a Drag&Drog of the TXT file into the WinForm and read the TXT at the same time.
This is an old question, but I'll provide another answer anyhow that doesn't involve using the Outlook objects.
This URL provides working code that is about 13 years old, but still seems to work, on how to handle the "FileGroupDescriptor" and "FileContents" data that Outlook passes to the DropDrop event. Just in case that link dies, here is the relevant code, copy/pasted directly:
DragEnter event:
private void Form1_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
{
// for this program, we allow a file to be dropped from Explorer
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{ e.Effect = DragDropEffects.Copy;}
// or this tells us if it is an Outlook attachment drop
else if (e.Data.GetDataPresent("FileGroupDescriptor"))
{ e.Effect = DragDropEffects.Copy;}
// or none of the above
else
{ e.Effect = DragDropEffects.None;}
}
DragDrop event:
private void Form1_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
{
string [] fileNames = null;
try
{
if ( e.Data.GetDataPresent(DataFormats.FileDrop,false) == true)
{
fileNames = (string []) e.Data.GetData(DataFormats.FileDrop);
// handle each file passed as needed
foreach( string fileName in fileNames)
{
// do what you are going to do with each filename
}
}
else if (e.Data.GetDataPresent("FileGroupDescriptor"))
{
//
// the first step here is to get the filename
// of the attachment and
// build a full-path name so we can store it
// in the temporary folder
//
// set up to obtain the FileGroupDescriptor
// and extract the file name
Stream theStream = (Stream) e.Data.GetData("FileGroupDescriptor");
byte [] fileGroupDescriptor = new byte[512];
theStream.Read(fileGroupDescriptor,0,512);
// used to build the filename from the FileGroupDescriptor block
StringBuilder fileName = new StringBuilder("");
// this trick gets the filename of the passed attached file
for(int i=76; fileGroupDescriptor[i]!=0; i++)
{ fileName.Append(Convert.ToChar(fileGroupDescriptor[i]));}
theStream.Close();
string path = Path.GetTempPath();
// put the zip file into the temp directory
string theFile = path+fileName.ToString();
// create the full-path name
//
// Second step: we have the file name.
// Now we need to get the actual raw
// data for the attached file and copy it to disk so we work on it.
//
// get the actual raw file into memory
MemoryStream ms = (MemoryStream) e.Data.GetData(
"FileContents",true);
// allocate enough bytes to hold the raw data
byte [] fileBytes = new byte[ms.Length];
// set starting position at first byte and read in the raw data
ms.Position = 0;
ms.Read(fileBytes,0,(int)ms.Length);
// create a file and save the raw zip file to it
FileStream fs = new FileStream(theFile,FileMode.Create);
fs.Write(fileBytes,0,(int)fileBytes.Length);
fs.Close(); // close the file
FileInfo tempFile = new FileInfo(theFile);
// always good to make sure we actually created the file
if ( tempFile.Exists == true)
{
// for now, just delete what we created
tempFile.Delete();
}
else
{ Trace.WriteLine("File was not created!");}
}
}
catch (Exception ex)
{
Trace.WriteLine("Error in DragDrop function: " + ex.Message);
// don't use MessageBox here - Outlook or Explorer is waiting !
}
}
Note that this code doesn't Dispose of objects that it should, such as the MemoryStream and FileStream objects.
You can get the running Outlook instance by using the GetActiveObject method which allows to obtain a running instance of the specified object from the running object table (ROT). Then you can automate Outlook to get the currently selected or opened item from which an attachment might be dragged. See C# app automates Outlook (CSAutomateOutlook) for the sample code.

Upload file to skydrive through SkyDrive API

I try to upload a text file to my skydrive or at least create new text file in SD and edit it's content, through SkyDrive API in my Windows 8 application.
How can I do that?
I tried to do something like that:
LiveConnectClient client = new LiveConnectClient(session);
var fileData = new Dictionary<string, object>();
fileData.Add("name", "new_file.txt");
try
{
LiveOperationResult fileOperationResult = await client.PutAsync("me/skydrive", fileData);
this.infoTextBlock.Text = fileOperationResult.ToString();
}
catch (LiveConnectException exception)
{
this.infoTextBlock.Text = exception.Message;
}
but I get error
"The provided request is not valid. The root SkyDrive folder cannot be updated."
If I write something like "me/skydrive/" I get
"The provided URL is not valid. The requested path '' is not supported".
Method LiveConnectClient.PutAsync allows me only to update existing properties (but not it's content).
How it should be done properly?
Btw - Is content on LCDC(http://msdn.microsoft.com/en-us/library/live/hh826531.aspx) updated? I'm asking because some methods, which are in documentation, doesn't exist in dlls (f.e. LiveConnectClient.Upload. There's only BackgroundUploadAsync).
Thanks for help in advance,
Micheal
Close but as I wrote: I can't use client.upload method because LiveConnectClient class doesn't contain it. That's why I asked about site content update.
Anyway - I've got an answer:
//create a StorageFile (here is one way to do that if it is stored in your ApplicationData)
StorageFile file = awaitApplicationData.Current.LocalFolder.GetFileAsync("yourfilename.txt");
try {
client = new LiveConnectClient(session);
LiveOperationResult operationResult = await client.BackgroundUploadAsync("me/skydrive", file.Name, file, OverwriteOption.Overwrite);
}
catch (LiveConnectException exception) {
//handle exception
}
You should use the Upload method on LiveConnectionClient. For example, see the Uploading Files example in the Live SDK. Something like ...
LiveOperationResult fileOperationResult =
await client.Upload("me/skydrive", /*file name here*/, /*file stream here*/);
Here's another way to upload a file from a console application using a SkyDriveApiClient downloaded from http://skydriveapiclient.codeplex.com/releases/view/103081
static void Main(string[] args)
{
var client = new SkyDriveServiceClient();
client.LogOn("YourEmail#hotmail.com", "password");
WebFolderInfo wfInfo = new WebFolderInfo();
WebFolderInfo[] wfInfoArray = client.ListRootWebFolders();
wfInfo = wfInfoArray[0];
client.Timeout = 1000000000;
string fn = #"test.txt";
if (File.Exists(fn))
{
client.UploadWebFile(fn, wfInfo);
}
}

Categories

Resources