I am working in a cross platform project, where we need to connect to Azure Notification Hub from Unity 3d.
We are trying to use the REST API, but we are having a problem with the generation of the SAS token. When trying to write to the stream we get an exception "Error writing request: The authentication or decryption has failed."
I think the generation of the SaS token has something wrong since it had to be modified to be cross platform and work within Unity.
Here is the code so far
using UnityEngine;
using System.Collections;
using System;
using System.Net;
using System.IO;
using System.Text;
/// <summary>
/// check https://msdn.microsoft.com/en-us/library/azure/dn495627.aspx
/// check also http://piotrwalat.net/hmac-authentication-in-asp-net-web-api/
/// </summary>
public class AzureNotificationHub : MonoBehaviour
{
public string CloudServiceNotificationHubPath = "cloudservicechat";
public string CloudServiceNotificationHubConnectionString =
"{CONNSTRINGHERE}";
public string NotificationHubUrl = "{HUBURLHERE}";
private ConnectionStringUtility objConnectionStringUtility = null;
public string SasToken;
public TextAsset CreateRegistrationTemplate = null;
// Use this for initialization
void Start()
{
this.objConnectionStringUtility = new ConnectionStringUtility(CloudServiceNotificationHubConnectionString);
this.SasToken = this.objConnectionStringUtility.getSaSToken(this.NotificationHubUrl, 10);
}
// Update is called once per frame
void Update()
{
}
private string atomContentType = "application/atom+xml;type=entry;charset=utf-8";
public void CreateRegistration()
{
string methodUrl = string.Format("{0}/{1}", this.NotificationHubUrl, "registrations/?api-version=2015-01");
string result = HttpPost(methodUrl);
}
/// <summary>
/// check http://stackoverflow.com/questions/9153181/adding-a-body-to-a-httpwebrequest-that-is-being-used-with-the-azure-service-mgmt
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
string HttpGet(string url)
{
HttpWebRequest req = WebRequest.Create(url)
as HttpWebRequest;
req.Headers.Add("Content-Type", this.atomContentType);
req.Headers.Add("Authorization", this.SasToken);
req.Headers.Add("x-ms-version", "2015-01");
req.Method = WebRequestMethods.Http.Get;
string result = null;
//writeStream.Write
using (HttpWebResponse resp = req.GetResponse()
as HttpWebResponse)
{
StreamReader reader =
new StreamReader(resp.GetResponseStream());
result = reader.ReadToEnd();
}
return result;
}
string HttpPost(string url)
{
string result = null;
string tokenForUrl = this.objConnectionStringUtility.getSaSToken(url, 10);
try
{
string body = this.CreateRegistrationTemplate.text;
body = body.Replace("{tags}", string.Empty);
body = body.Replace("{ChannelUri}", this.NotificationHubUrl);
byte[] bodyArray = System.Text.Encoding.UTF8.GetBytes(body);
HttpWebRequest req = WebRequest.Create(url)
as HttpWebRequest;
req.ContentType = this.atomContentType;
//req.Headers.Add(HttpRequestHeader.Authorization, this.SasToken);
req.Headers.Add(HttpRequestHeader.Authorization, tokenForUrl);
req.Headers.Add("x-ms-version", "2015-01");
req.Method = WebRequestMethods.Http.Post;
Stream writeStream = req.GetRequestStream();
writeStream.Write(bodyArray, 0, bodyArray.Length);
writeStream.Flush();
writeStream.Close();
using (HttpWebResponse resp = req.GetResponse()
as HttpWebResponse)
{
StreamReader reader =
new StreamReader(resp.GetResponseStream());
result = reader.ReadToEnd();
}
}
catch (Exception ex)
{
result = ex.Message;
}
return result;
}
}
public partial class ConnectionStringUtility
{
public string Endpoint { get; private set; }
public string SasKeyName { get; private set; }
public string SasKeyValue { get; private set; }
private string sasTokenn { get; set; }
public ConnectionStringUtility(string connectionString)
{
//Parse Connectionstring
char[] separator = { ';' };
string[] parts = connectionString.Split(separator);
for (int i = 0; i < parts.Length; i++)
{
if (parts[i].StartsWith("Endpoint"))
Endpoint = "https" + parts[i].Substring(11);
if (parts[i].StartsWith("SharedAccessKeyName"))
SasKeyName = parts[i].Substring(20);
if (parts[i].StartsWith("SharedAccessKey"))
SasKeyValue = parts[i].Substring(16);
}
}
/// <summary>
/// check http://buchananweb.co.uk/security01i.aspx
/// </summary>
/// <param name="uri"></param>
/// <param name="minUntilExpire"></param>
/// <returns></returns>
public string getSaSToken(string uri, int minUntilExpire)
{
string targetUri = Uri.EscapeDataString(uri.ToLower()).ToLower();
// Add an expiration in seconds to it.
long expiresOnDate = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
expiresOnDate += minUntilExpire * 60 * 1000;
long expires_seconds = expiresOnDate / 1000;
String toSign = targetUri + "\n" + expires_seconds;
HmacSignatureCalculator hmacSigner = new HmacSignatureCalculator();
System.Security.Cryptography.SHA256Managed crypto = new System.Security.Cryptography.SHA256Managed();
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
var messageBuffer = ConvertStringToBinary(toSign, encoding);
var keyBuffer = ConvertStringToBinary(SasKeyValue, encoding);
var hmacKey = CreateKey(keyBuffer);
var signedMessage = Sign(hmacKey, messageBuffer);
string signature = Uri.EscapeDataString(signedMessage);
return "SharedAccessSignature sr=" + targetUri + "&sig=" + signature + "&se=" + expires_seconds + "&skn=" + SasKeyName;
}
private byte[] CreateKey(byte[] keyBuffer)
{
System.Security.Cryptography.SHA256Managed crypto = new System.Security.Cryptography.SHA256Managed();
var computedHash = crypto.ComputeHash(keyBuffer);
return computedHash;
}
public string Sign(byte[] hmacKey, byte[] messageBuffer)
{
using (System.Security.Cryptography.SHA256Managed crypto = new System.Security.Cryptography.SHA256Managed())
{
var hash = crypto.ComputeHash(hmacKey);
var signature = Convert.ToBase64String(hash);
return signature;
}
}
public byte[] ConvertStringToBinary(string value, Encoding encoding)
{
//Requires.NotNull(value, "value");
//Requires.NotNull(encoding, "encoding");
return encoding.GetBytes(value);
}
}
Any ideas what I should do?
Thanks for the help.
Related
I'm testing ServiceStack.OrmLite.Oracle (5.5.1) but can't save data to database when create model with Sequence attribute. Try to test with API & generated SQL, API not insert data but generated SQL is correct. How to fix this?
using System;
using System.Data;
using NUnit.Framework;
using ServiceStack.DataAnnotations;
using ServiceStack.OrmLite;
namespace Tests
{
public class DatabaseTest
{
private readonly IDbConnection _db;
public DatabaseTest()
{
var dbFactory = new OrmLiteConnectionFactory(
#"Data Source = (DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = ora-test)(PORT = 1521))(CONNECT_DATA =(SERVER = DEDICATED)(SERVICE_NAME = twcms12c))); User Id=scott; Password=Ab123456",
OracleDialect.Provider);
_db = dbFactory.OpenDbConnection();
}
[Test]
public void CustomerInsertTest()
{
_db.DropAndCreateTable<Person>();
var customer = new Person {FirstName = "John", LastName = "Smith", Age = 20};
//Insert by API not work
_db.Insert(customer);
var customers = _db.Select<Person>();
Console.WriteLine("Person count (API) = {0}",customers.Count);
//Insert by SQL working
_db.ExecuteSql(_db.ToInsertStatement(customer));
customers = _db.Select<Person>();
Console.WriteLine("Person count (SQL) = {0}",customers.Count);
}
}
public class Person
{
[AutoIncrement]
[Sequence("PERSON_SEQ")]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int? Age { get; set; }
}
}
And output result is:
Person count (API) = 0
Person count (SQL) = 1
In ServiceStack.OrmLite.Oracle (5.5.1) have a bug in method GetNextValue (ServiceStack.OrmLite.Oracle.OracleOrmLiteDialectProvider.cs):
private object GetNextValue(IDbCommand dbCmd, string sequence, object value)
{
if (value.ToString() != "0")
{
object retObj;
if (long.TryParse(value.ToString(), out var nv))
{
LastInsertId = nv;
retObj = LastInsertId;
}
else
{
LastInsertId = 0;
retObj = value;
}
return retObj;
}
dbCmd.CommandText = $"SELECT {Quote(sequence)}.NEXTVAL FROM dual";
long result = (long)dbCmd.LongScalar();
LastInsertId = result;
return result;
}
I change it to:
private object GetNextValue(IDbCommand dbCmd, string sequence, object value)
{
if (value.ToString() != "0")
{
object retObj;
if (long.TryParse(value.ToString(), out var nv))
{
LastInsertId = nv;
retObj = LastInsertId;
}
else
{
LastInsertId = 0;
retObj = value;
}
return retObj;
}
var lastSql = dbCmd.CommandText;
dbCmd.CommandText = $"SELECT {Quote(sequence)}.NEXTVAL FROM dual";
long result = (long)dbCmd.LongScalar();
LastInsertId = result;
dbCmd.CommandText = lastSql;
return result;
}
and it work well.
P/s: I have create a pull request it was accepted by ServiceStack.
I've installed filepicker control from Nuget and added tried adding reference from MonoTouch10 folder and later from github to my xamarin.ios project.
FileData file = await CrossFilePicker.Current.PickFile();
if (file != null) { }
this is the code i added to my browse button, after selecting a file from iCloud drive, control never comes to "if condition".
and again when i click on browse button for second time, app crashes saying "only one operation can be active at a time".
Modifying the source code of the FilePickerImplementation plugin for the iOS platform worked, in this way:
using Foundation;
using MobileCoreServices;
using Plugin.FilePicker.Abstractions;
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using UIKit;
using System.Diagnostics;
namespace Plugin.FilePicker
{
/// <summary>
/// Implementation for FilePicker
/// </summary>
public class FilePickerImplementation : NSObject, IUIDocumentMenuDelegate, IFilePicker
{
private int _requestId;
private TaskCompletionSource<FileData> _completionSource;
/// <summary>
/// Event which is invoked when a file was picked
/// </summary>
public EventHandler<FilePickerEventArgs> Handler
{
get;
set;
}
private void OnFilePicked(FilePickerEventArgs e)
{
Handler?.Invoke(null, e);
}
public void DidPickDocumentPicker(UIDocumentMenuViewController documentMenu, UIDocumentPickerViewController documentPicker)
{
documentPicker.DidPickDocument += DocumentPicker_DidPickDocument;
documentPicker.WasCancelled += DocumentPicker_WasCancelled;
documentPicker.DidPickDocumentAtUrls += DocumentPicker_DidPickDocumentAtUrls;
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(documentPicker, true, null);
}
private void DocumentPicker_DidPickDocumentAtUrls(object sender, UIDocumentPickedAtUrlsEventArgs e)
{
var control = (UIDocumentPickerViewController)sender;
foreach (var url in e.Urls)
DocumentPicker_DidPickDocument(control, new UIDocumentPickedEventArgs(url));
control.Dispose();
}
private void DocumentPicker_DidPickDocument(object sender, UIDocumentPickedEventArgs e)
{
var securityEnabled = e.Url.StartAccessingSecurityScopedResource();
var doc = new UIDocument(e.Url);
var data = NSData.FromUrl(e.Url);
var dataBytes = new byte[data.Length];
System.Runtime.InteropServices.Marshal.Copy(data.Bytes, dataBytes, 0, Convert.ToInt32(data.Length));
string filename = doc.LocalizedName;
string pathname = doc.FileUrl?.ToString();
// iCloud drive can return null for LocalizedName.
if (filename == null)
{
// Retrieve actual filename by taking the last entry after / in FileURL.
// e.g. /path/to/file.ext -> file.ext
// filesplit is either:
// 0 (pathname is null, or last / is at position 0)
// -1 (no / in pathname)
// positive int (last occurence of / in string)
var filesplit = pathname?.LastIndexOf('/') ?? 0;
filename = pathname?.Substring(filesplit + 1);
}
OnFilePicked(new FilePickerEventArgs(dataBytes, filename, pathname));
}
/// <summary>
/// Handles when the file picker was cancelled. Either in the
/// popup menu or later on.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void DocumentPicker_WasCancelled(object sender, EventArgs e)
{
{
var tcs = Interlocked.Exchange(ref _completionSource, null);
tcs.SetResult(null);
}
}
/// <summary>
/// Lets the user pick a file with the systems default file picker
/// For iOS iCloud drive needs to be configured
/// </summary>
/// <returns></returns>
public async Task<FileData> PickFile()
{
var media = await TakeMediaAsync();
return media;
}
private Task<FileData> TakeMediaAsync()
{
var id = GetRequestId();
var ntcs = new TaskCompletionSource<FileData>(id);
if (Interlocked.CompareExchange(ref _completionSource, ntcs, null) != null)
throw new InvalidOperationException("Only one operation can be active at a time");
var allowedUtis = new string[] {
UTType.UTF8PlainText,
UTType.PlainText,
UTType.RTF,
UTType.PNG,
UTType.Text,
UTType.PDF,
UTType.Image,
UTType.UTF16PlainText,
UTType.FileURL
};
var importMenu =
new UIDocumentMenuViewController(allowedUtis, UIDocumentPickerMode.Import)
{
Delegate = this,
ModalPresentationStyle = UIModalPresentationStyle.Popover
};
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(importMenu, true, null);
var presPopover = importMenu.PopoverPresentationController;
if (presPopover != null)
{
presPopover.SourceView = UIApplication.SharedApplication.KeyWindow.RootViewController.View;
presPopover.PermittedArrowDirections = UIPopoverArrowDirection.Down;
}
Handler = null;
Handler = (s, e) => {
var tcs = Interlocked.Exchange(ref _completionSource, null);
tcs?.SetResult(new FileData(e.FilePath, e.FileName, () => { var url = new Foundation.NSUrl(e.FilePath); return new FileStream(url.Path, FileMode.Open, FileAccess.Read); }));
};
return _completionSource.Task;
}
public void WasCancelled(UIDocumentMenuViewController documentMenu)
{
var tcs = Interlocked.Exchange(ref _completionSource, null);
tcs?.SetResult(null);
}
private int GetRequestId()
{
var id = _requestId;
if (_requestId == int.MaxValue)
_requestId = 0;
else
_requestId++;
return id;
}
public async Task<bool> SaveFile(FileData fileToSave)
{
try
{
var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var fileName = Path.Combine(documents, fileToSave.FileName);
File.WriteAllBytes(fileName, fileToSave.DataArray);
return true;
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
return false;
}
}
public void OpenFile(NSUrl fileUrl)
{
var docControl = UIDocumentInteractionController.FromUrl(fileUrl);
var window = UIApplication.SharedApplication.KeyWindow;
var subViews = window.Subviews;
var lastView = subViews.Last();
var frame = lastView.Frame;
docControl.PresentOpenInMenu(frame, lastView, true);
}
public void OpenFile(string fileToOpen)
{
var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var fileName = Path.Combine(documents, fileToOpen);
if (NSFileManager.DefaultManager.FileExists(fileName))
{
var url = new NSUrl(fileName, true);
OpenFile(url);
}
}
public async void OpenFile(FileData fileToOpen)
{
var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var fileName = Path.Combine(documents, fileToOpen.FileName);
if (NSFileManager.DefaultManager.FileExists(fileName))
{
var url = new NSUrl(fileName, true);
OpenFile(url);
}
else
{
await SaveFile(fileToOpen);
OpenFile(fileToOpen);
}
}
}
}
To answer my own question, i customized in plugin, like
Used DocumentPicker_DidPickDocumentAtUrls event instead of DocumentPicker_DidPickDocument.
while returning selected file used
new FileData(e.FilePath, e.FileName, () =>
{
var url = new Foundation.NSUrl(e.FilePath);
return new FileStream(url.Path, FileMode.Open, FileAccess.Read);
})
This solved my issue. Thanks.
There are several forks of the FilePicker Xamarin plugin. I recommend the following project, since it's the most actively maintained one:
https://github.com/jfversluis/FilePicker-Plugin-for-Xamarin-and-Windows (note: I'm one of the contributors to the project).
With this version of the plugin file picking should work. The example code from sandeep's answer was already incorporated into the latest version of the plugin. Be sure to read the README.md's Troubleshooting page in case you're getting problems.
I am using xamarin forms. I want to pick photo from gallery for my iphone app and want to save it in Azure DB. Is there any solution available for xamarin forms. Or Is there any plugin available to deal with Photo, Document, or Audio. Any help is appreciated.
Using dependency service you can take or pick photos from Android / iPhone :-
Please refer to code below and try to implement the similar code:-
This is the interface in PCL:-
public interface IGalleryProvider
{
Task<List<AttachmentMediaFile>> PickPhotoAsync();
Task<List<AttachmentMediaFile>> PickAudioAsync();
Task<List<AttachmentMediaFile>> PickDocumentAsync();
Task<AttachmentMediaFile> PickProfilePhotoAsync();
Task SaveToGalleryAsync(AttachmentMediaFile file);
}
Below is the code using which you can pick or take photos from iPhone only:-
using AssetsLibrary;
using AVFoundation;
using ELCImagePicker;
using Foundation;
using MediaPlayer;
using MobileCoreServices;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UIKit;
[assembly: Xamarin.Forms.Dependency(typeof(GalleryProvider))]
namespace SanketSample.MobileApp.Sample.iOS.Common
{
public class GalleryProvider : IGalleryProvider
{
private TaskCompletionSource<List<AttachmentMediaFile>> _audioPickedTask;
public async Task<List<AttachmentMediaFile>> PickAudioAsync()
{
_audioPickedTask = new TaskCompletionSource<List<AttachmentMediaFile>>();
var picker = new MPMediaPickerController();
ShowViewController(picker);
picker.ItemsPicked += OnAudioPicked;
picker.DidCancel += OnCancel;
var media = await _audioPickedTask.Task;
return media;
}
private void OnCancel(object sender, EventArgs e)
{
var picker = sender as MPMediaPickerController;
picker.DidCancel -= OnCancel;
picker.DismissViewController(true, null);
_audioPickedTask.TrySetResult(new List<AttachmentMediaFile>());
}
private void OnAudioPicked(object sender, ItemsPickedEventArgs e)
{
var media = new List<AttachmentMediaFile>();
var picker = sender as MPMediaPickerController;
picker.ItemsPicked -= OnAudioPicked;
picker.DismissViewController(true, null);
if (e.MediaItemCollection.Items != null)
{
foreach (var item in e.MediaItemCollection.Items)
{
//var vm1 = (new ViewModelLocator()).AttachmentsVM.SelectedAttachments.Add();
if (!item.IsCloudItem)
{
try
{
//var error = new NSError();
//var asset = new AVUrlAsset(item.AssetURL);
//var exporter = new AVAssetExportSession(asset, item.Title);
//exporter.OutputFileType = "com.apple.m4a-audio";
//AVAssetExportSession session = new AVAssetExportSession(asset, "");
//var reader = new AVAssetReader(asset, out error);
//var settings = new NSDictionary();
//Func<byte[]> bytesGetter = e.MediaItemCollection
//TODO item.Title, item.Title SSSanket,
//var _asset = AVAsset.FromUrl(NSUrl.FromFilename(item.AssetURL.ToString()));
//var _exportSession = new AVAssetExportSession(_asset, AVAssetExportSession.PresetPassthrough);
//_exportSession.OutputFileType = AVFileType.Aiff;
// media.Add(new AttachmentMediaFile(item.AssetURL.AbsoluteString, AttachmentMediaFileType.Audio, null , item.Title));
}
catch (Exception ex)
{
// throw ;
}
}
}
}
_audioPickedTask.TrySetResult(media);
}
public async Task<List<AttachmentMediaFile>> PickDocumentAsync()
{
var task = new TaskCompletionSource<List<AttachmentMediaFile>>();
var allowedUTIs = new string[]
{
UTType.UTF8PlainText,
UTType.PlainText,
UTType.RTF,
UTType.Text,
UTType.PDF,
"com.microsoft.word.doc",
"com.microsoft.excel.xls"
};
var pickerMenu = new UIDocumentMenuViewController(allowedUTIs, UIDocumentPickerMode.Open);
pickerMenu.DidPickDocumentPicker += (sender, args) =>
{
args.DocumentPicker.DidPickDocument += (sndr, pArgs) =>
{
var securityEnabled = pArgs.Url.StartAccessingSecurityScopedResource();
NSError err;
var fileCoordinator = new NSFileCoordinator();
var docs = new List<AttachmentMediaFile>();
// Read bytes.
fileCoordinator.CoordinateRead(pArgs.Url, 0, out err, (NSUrl newUrl) =>
{
NSData data = NSData.FromUrl(newUrl);
docs.Add(new AttachmentMediaFile(pArgs.Url.AbsoluteString, AttachmentMediaFileType.Doc, data.ToArray(),null));
task.TrySetResult(docs);
});
};
ShowViewController(args.DocumentPicker);
};
ShowViewController(pickerMenu);
return await task.Task;
}
public async Task<List<AttachmentMediaFile>> PickPhotoAsync()
{
var media = new List<AttachmentMediaFile>();
var picker = ELCImagePickerViewController.Instance;
picker.MaximumImagesCount = 15;
ShowViewController(picker);
await picker.Completion.ContinueWith(result =>
{
picker.BeginInvokeOnMainThread(() =>
{
picker.DismissViewController(true, null);
if (!result.IsCanceled && result.Exception == null)
{
var imageEditor = new ImageEditor();
var items = result.Result as List<AssetResult>;
foreach (var item in items)
{
var bbytes= imageEditor.ResizeImage(item.Image, 1024, 1024);
media.Add(new AttachmentMediaFile(item.Path, AttachmentMediaFileType.Photo, bbytes, item.Name));
}
}
});
});
return media;
}
public async Task<AttachmentMediaFile> PickProfilePhotoAsync()
{
AttachmentMediaFile selectMediaFile = null;
var picker = ELCImagePickerViewController.Instance;
picker.MaximumImagesCount = 1;
ShowViewController(picker);
await picker.Completion.ContinueWith(result =>
{
picker.BeginInvokeOnMainThread(() =>
{
picker.DismissViewController(true, null);
if (!result.IsCanceled && result.Exception == null)
{
var imageEditor = new ImageEditor();
var items = result.Result as List<AssetResult>;
foreach (var item in items)
{
var bbytes = imageEditor.ResizeImage(item.Image, 1024, 1024);
selectMediaFile = new AttachmentMediaFile(item.Path, AttachmentMediaFileType.Photo, bbytes, item.Name);
}
}
});
});
return selectMediaFile;
}
public async Task SaveToGalleryAsync(AttachmentMediaFile file)
{
var bytes = file.GetBytes();
var originalImage = ImageEditor.ImageFromByteArray(bytes);
var library = new ALAssetsLibrary();
var orientation = (ALAssetOrientation)originalImage.Orientation;
var nsUrl = await library.WriteImageToSavedPhotosAlbumAsync(originalImage.CGImage, orientation);
}
private void ShowViewController(UIViewController controller)
{
var topController = UIApplication.SharedApplication.KeyWindow.RootViewController;
while (topController.PresentedViewController != null)
{
topController = topController.PresentedViewController;
}
topController.PresentViewController(controller, true, null);
}
}
}
Below are useful classes :-
public class AttachmentMediaFile
{
private readonly Func<byte[]> _bytesGetter;
public string LocalPath { get; private set; }
public string Name { get; private set; }
public AttachmentMediaFileType Type { get; private set; }
public AttachmentMediaFile(string localPath, AttachmentMediaFileType type, byte[] bytesGetter, string name = null)
{
LocalPath = localPath;
Type = type;
_bytesGetter = () =>
{
return bytesGetter;
};
if (string.IsNullOrEmpty(name))
{
Name = FileNameHelper.PrepareName(localPath);
}
else
{
Name = name;
}
}
public byte[] GetBytes()
{
return _bytesGetter();
}
}
public enum AttachmentMediaFileType
{
Photo = 0,
Audio = 1,
Doc = 2,
Video = 3,
}
public static class FileNameHelper
{
private const string Prefix = "IMG";
public static string PrepareName(string localPath)
{
var name = string.Empty;
if (!string.IsNullOrEmpty(localPath))
{
name = localPath.Split('/').Last();
}
return name;
}
public static string GenerateUniqueFileName(Extension extension)
{
var format = ".jpg";
var fileName = string.Concat(Prefix, '_', DateTime.UtcNow.Ticks, format);
return fileName;
}
public enum Extension
{
JPG
}
}
Now if you want to store your data to Azure Server Table so you are already using Azure mobile service client SDK similarly you need Blob nuget from Azure using which you can save your photos by making blob objects to Azure server :-
use blob helper nuget from manage nuget package install Microsoft.WindowsAzure.Storage.Auth;
Microsoft.WindowsAzure.Storage.Blob;
this and try to implement the code similarly I given bellow:-
using Acr.UserDialogs;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using SanketSample.MobileApp.sample.Business.Azure;
using SanketSample.MobileApp.sample.Business.Interfaces;
using SanketSample.MobileApp.sample.Models;
using SanketSample.MobileApp.sample.Models.AzureTables;
using SanketSample.MobileApp.sample.Models.Media;
using SanketSample.MobileApp.sample.Utils;
using Xamarin.Forms;
namespace SanketSample.MobileApp.Sanket.Common.Media
{
public class BlobHelper
{
private const string ContainerName = "attachments";
private Dictionary<string, TaskCompletionSource<bool>> _tasks;
private IHttpService _httpservice { get; set; }
#region Singleton Implementation
private static readonly Lazy<BlobHelper> lazyInstance = new Lazy<BlobHelper>(() => new BlobHelper(), true);
private BlobHelper()
{
_tasks = new Dictionary<string, TaskCompletionSource<bool>>();
}
public static BlobHelper Instance
{
get { return lazyInstance.Value; }`enter code here`
}
#endregion Singleton Implementation
public async Task UploadAttachments(IList<AttachmentFile> attachments, long associatedRecordId, string category)
{
foreach (var attachment in attachments)
{
await UploadAttachment(attachment, associatedRecordId, category);
}
}
public async Task UploadAttachment(AttachmentFile attachment, long associatedRecordId, string category)
{
try
{
CommonHelper commonHelper = new CommonHelper();
attachment.ContainerName = ContainerName;
attachment.AssociatedRecordId = associatedRecordId;
//attachment.RecordId = commonHelper.GenerateRecordId();
if (attachment.FileExtension == null)
{
attachment.FileExtension = ConvertType(attachment.MediaFile);
}
attachment.Category = category;
var taskCompletionSource = new TaskCompletionSource<bool>();
if (!_tasks.ContainsKey(attachment.Name))
{ _tasks.Add(attachment.Name, taskCompletionSource); }
else
{
_tasks[attachment.Name] = taskCompletionSource;
}
// _tasks.Add(attachment.Name, taskCompletionSource);
var attachmentsTableOnline = AzureServiceProvider.Instance.GetRemoteTable<AttachmentFile>();
if (CheckInternetConnection.IsConnected())
{
await attachmentsTableOnline.InsertAsync(attachment);
}
var attachmentsTableOffline = AzureServiceProvider.Instance.GetLocalTable<AttachmentFile>();
await attachmentsTableOffline.InsertAsync(attachment);
if (!string.IsNullOrEmpty(attachment.SasQueryString))
{
var credentials = new StorageCredentials(attachment.SasQueryString);
var imageUri = new Uri(attachment.Uri);
var container = new CloudBlobContainer(new Uri(string.Format("https://{0}/{1}",
imageUri.Host, attachment.ContainerName)), credentials);
var blobFromSASCredential = container.GetBlockBlobReference(attachment.Name);
try
{
var bytes = attachment.MediaFile.GetBytes();
await blobFromSASCredential.UploadFromByteArrayAsync(bytes, 0, bytes.Length);
if (CheckInternetConnection.IsConnected())
{
await attachmentsTableOnline.UpdateAsync(attachment);
}
await attachmentsTableOffline.UpdateAsync(attachment);
taskCompletionSource.TrySetResult(true);
}
catch (Microsoft.WindowsAzure.Storage.StorageException ex)
{
// Throws from UploadFromByteArrayAsync, but image uploaded.
System.Diagnostics.Debug.WriteLine($"BlobHelper: {ex}");
taskCompletionSource.TrySetResult(true);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"BlobHelper: {ex}");
taskCompletionSource.TrySetResult(false);
}
}
}
catch (Exception ca)
{
//throw ca;
}
}
/// <summary>
/// Downloads Blob Data boject and returns the Byts[] data
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
public async Task<byte[]> DownloadAttachment(AttachmentFile file)
{
byte[] bytes = null;
var fileContainer = file.Uri.Replace(file.Name, string.Empty);
var container = new CloudBlobContainer(new Uri(fileContainer));
var blob = container.GetBlockBlobReference(file.Name);
using (var stream = new MemoryStream())
{
var isExist = await blob.ExistsAsync();
if (isExist)
{
await blob.DownloadToStreamAsync(stream);
bytes = stream.ToArray();
}
}
return bytes;
}
/// <summary>
/// Updates the Attachments Byts in the Azure Local Tables.
/// </summary>
/// <param name="AttachmentFileRecordId">Attachments Byte[] Data.</param>
/// <returns></returns>
public async Task<byte[]> DownloadAttachmentFileDetails(long? AttachmentFileRecordId, IHttpService service)
{
_httpservice = service;
try
{
ResponseWrapper<AttachmentFileDetail> result = new ResponseWrapper<AttachmentFileDetail>();
if (AttachmentFileRecordId != null)
{
var request = Constants.API_BASE_URL + string.Format(Constants.API_ATTACHMENTS_PARAMETERS, AttachmentFileRecordId);
var response = await _httpservice.SendRequestAsync(HttpMethod.Get, request);
result.Status = response.Status;
if (response.IsSuccess)
{
result.Result = JsonConvert.DeserializeObject<AttachmentFileDetail>(response.Result);
if (result.Result == null)
{
result.Status = System.Net.HttpStatusCode.InternalServerError;
}
else
{
var output = result.Result;
var data = new List<AttachmentFileDetail>() { output };
await AzureServiceProvider.Instance.DatabaseService.InsertDataToLocalDB<AttachmentFileDetail>(data);
return result.Result.FileByteArray;
}
}
}
}
catch (Exception ex)
{
////throw ex;
}
finally
{
}
return null;
}
private string ConvertType(AttachmentMediaFile file)
{
switch (file.Type)
{
case AttachmentMediaFileType.Doc:
return "doc";
case AttachmentMediaFileType.Audio:
return "mp3";
}
return "jpeg";
}
}
}
media plugin on github
works pretty well for me.
Here is the code, but it prompts error:
The image o3lceiy3.ioa201305211013360129.vhd does not exist.
the subscriptionId and X509Certificate2 are valid
internal class Program
{
public static X509Certificate2 Certificate { get; set; }
private static void Main(string[] args)
{
const string subscriptionId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
//#"https://management.core.windows.net/<subscription-id>/services/hostedservices/<cloudservice-name>/deployments";
var url = string.Format("https://management.core.windows.net/{0}/services/hostedservices/{1}/deployments",
subscriptionId, "edoc2cloudtest");
var myReq = (HttpWebRequest)WebRequest.Create(url);
myReq.Method = "POST";
myReq.Headers.Add("x-ms-version", "2012-03-01");
myReq.Proxy = null;
myReq.Timeout = 30000;
myReq.ContentType = "application/xml";
var postData = ReadConfig();
using (var reqStream = myReq.GetRequestStream())
{
var data = Encoding.UTF8.GetBytes(postData);
reqStream.Write(data, 0, data.Length);
reqStream.Flush();
}
Certificate = GetX509Certificate();
myReq.ClientCertificates.Add(Certificate);
try
{
var myRes = (HttpWebResponse) myReq.GetResponse();
}
catch (WebException exWeb)
{
// Parse the web response.
Stream responseStream = exWeb.Response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
XmlDocument xDocResp = new XmlDocument();
xDocResp.Load(reader);
HttpWebResponse responseStatus = (HttpWebResponse)exWeb.Response;
responseStream.Close();
reader.Close();
var result = NiceFormatXml(xDocResp);
Console.WriteLine(result);
}
}
private static string NiceFormatXml(XmlDocument xDoc)
{
StringBuilder niceString = new StringBuilder();
StringWriter strWriter = new StringWriter(niceString);
XmlTextWriter xmlWriter = new XmlTextWriter(strWriter);
xmlWriter.Formatting = Formatting.Indented;
xDoc.WriteTo(xmlWriter);
xmlWriter.Close();
strWriter.Close();
return niceString.ToString();
}
private static X509Certificate2 GetX509Certificate()
{
X509Certificate2 certificate2 = null;
var store = new X509Store("MY", StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
var collection = store.Certificates;
var fcollection = collection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
const string certificateThumbprint = "7dfbc7369306ed096b7e5c7b4ba6e99f190240e9";
store.Close();
if (fcollection.Count > 0)
{
foreach (var variable in fcollection)
{
if (variable.Thumbprint != null &&
variable.Thumbprint.Equals(certificateThumbprint, StringComparison.InvariantCultureIgnoreCase))
{
certificate2 = variable;
}
}
}
return certificate2;
}
private static string ReadConfig()
{
string path = System.AppDomain.CurrentDomain.BaseDirectory + "Edoc2Cloud.xml";
//string path = System.AppDomain.CurrentDomain.BaseDirectory + "VM-CreateVM.xml";
string s;
using (var sr = new StreamReader(path, Encoding.GetEncoding("GB2312")))
{
s = sr.ReadToEnd();
}
return s;
}
}
Here is the XML:
<Deployment xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Name>EDoc2Test</Name>
<DeploymentSlot>Staging</DeploymentSlot>
<Label>EDoc2Testlabe</Label>
<RoleList>
<Role>
<RoleName>EDoc2TestRoleName</RoleName>
<RoleType>PersistentVMRole</RoleType>
<ConfigurationSets>
<ConfigurationSet>
<ConfigurationSetType>WindowsProvisioningConfiguration</ConfigurationSetType>
<ComputerName>computer-name</ComputerName>
<AdminPassword>APasswor_324d</AdminPassword>
<EnableAutomaticUpdates>true</EnableAutomaticUpdates>
</ConfigurationSet>
</ConfigurationSets>
<AvailabilitySetName>EDoc2TestSetName</AvailabilitySetName>
<OSVirtualHardDisk>
<HostCaching>ReadWrite</HostCaching>
<DiskName>SomeName-0-20121007173943</DiskName>
<MediaLink>http://portalvhdsx4flx9dhmjyt1.blob.core.windows.net/vhds/o3lceiy3.ioa201305211013360129.vhd</MediaLink>
<SourceImageName>o3lceiy3.ioa201305211013360129.vhd</SourceImageName>
</OSVirtualHardDisk>
<RoleSize>Medium</RoleSize>
</Role>
Based on the error you're receiving and the XML you've specified, can you please check if there is an image by the name o3lceiy3.ioa201305211013360129.vhd in your custom images? You could find that information by logging into the portal and going to Virtual Machines --> Images.
Documentation regarding <SourceImageName> parameter states that it is needed when you want to create a virtual machine either by using system or custom images.
You can read the complete documentation here: http://msdn.microsoft.com/en-us/library/windowsazure/jj157186.aspx#OSVirtualHardDisk.
Using the Google Docs Java API with a Google Apps account, is it possible to impersonate a user and download a file?
When I run the program below, it is clearly logging on to the domain and impersonating the user because it retrieves the details of one of the files and prints out the file title. However, when it tries to download the file, a ServiceForbiddenException is thrown.
If it is not possible with the Java API, does anyone know if it is possible for my program to write an HTTP request to download the file using the Protocol API?
public class AuthExample {
private static DocsService docService = new DocsService("Auth Example");
public static void main(String[] args)
throws Exception
{
String adminUser = args[0];
String adminPassword = args[1];
String authToken = args[2];
String impersonatedUser = args[3];
loginToDomain(adminUser, adminPassword, authToken);
URL url = new URL( "https://docs.google.com/feeds/" + impersonatedUser + "/private/full" );
DocumentListFeed feed = docService.getFeed(url, DocumentListFeed.class);
DocumentListEntry entry = feed.getEntries().get(0);
String title = entry.getTitle().getPlainText();
System.out.println( title );
String type = entry.getType();
if ( type.equals("document") )
{
String encodedAdminUser = URLEncoder.encode(adminUser);
String resourceId = entry.getResourceId();
String resourceIdNoPrefix = resourceId.substring( resourceId.indexOf(':')+1 );
String downloadUrl =
"https://docs.google.com/feeds/download/documents/Export" +
"?xoauth_requestor=" + encodedAdminUser +
"&docId=" + resourceIdNoPrefix +
"&exportFormat=doc";
downloadFile( downloadUrl, title + ".doc" );
}
}
private static void loginToDomain(String adminUser, String adminPassword, String authToken)
throws OAuthException, AuthenticationException
{
String domain = adminUser.substring( adminUser.indexOf('#')+1 );
GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
oauthParameters.setOAuthConsumerKey(domain);
oauthParameters.setOAuthConsumerSecret(authToken);
oauthParameters.setOAuthType(OAuthType.TWO_LEGGED_OAUTH);
oauthParameters.setScope("https://docs.google.com/feeds/ http://spreadsheets.google.com/feeds/ http://docs.googleusercontent.com/");
docService.useSsl();
docService.setOAuthCredentials(oauthParameters, new OAuthHmacSha1Signer());
docService.setUserCredentials(adminUser, adminPassword);
}
// Method pasted directly from Google documentation
public static void downloadFile(String exportUrl, String filepath)
throws IOException, MalformedURLException, ServiceException
{
System.out.println("Exporting document from: " + exportUrl);
MediaContent mc = new MediaContent();
mc.setUri(exportUrl);
MediaSource ms = docService.getMedia(mc);
InputStream inStream = null;
FileOutputStream outStream = null;
try {
inStream = ms.getInputStream();
outStream = new FileOutputStream(filepath);
int c;
while ((c = inStream.read()) != -1) {
outStream.write(c);
}
} finally {
if (inStream != null) {
inStream.close();
}
if (outStream != null) {
outStream.flush();
outStream.close();
}
}
}
}
Impersonation will work as intended if you use Oauth2 with ServiceAccounts