加密和上传 & 解密和下载图像 to/from Xamarin Forms 中的 Firebase 存储
Encrypt and Upload & Decrypt and Download Image to/from Firebase Storage in Xamarin Forms
我正在尝试使用 AES 加密图像并将其上传到 Firebase 存储,然后解密并下载它。我正在使用以下方法:
private async void BtnUpload_Clicked(object sender, EventArgs e)
{
var fileStream = FileEncrypt(file.Path);
var user = await GetUser(localEmail);
await firebaseHelper.UploadFile(fileStream.Result, Path.GetFileName(file.Path), user.UserID);
var downloadurl = await firebaseHelper.GetFile(Path.GetFileName(file.Path), user.UserID);
await firebaseHelper.UploadURL(Path.GetFileName(file.Path), downloadurl.ToString(), user.UserID);
await DisplayAlert("Success", "Uploaded", "OK");
}
private async Task<FileStream> FileEncrypt(string inputFile)
{
var user = await GetUser(localEmail);
FileStream fsCrypt = new FileStream(inputFile + ".aes", FileMode.Create);
//Set Rijndael symmetric encryption algorithm
RijndaelManaged AES = new RijndaelManaged();
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Padding = PaddingMode.PKCS7;
var key = new Rfc2898DeriveBytes(user.Key, user.Salt, 50000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CFB;
// write salt to the begining of the output file
fsCrypt.Write(user.Salt, 0, user.Salt.Length);
CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
//create a buffer (1mb) so only this amount will allocate in the memory and not the whole file
//1048576 is 1MB in binary
byte[] buffer = new byte[1048576];
int read;
try
{
while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
{
//Application.DoEvents(); // -> for responsive GUI, using Task will be better!
cs.Write(buffer, 0, read);
}
//fsIn.Close();//causes error
}
catch (Exception ex)
{
DisplayAlert("Error", "Error: " + ex.Message, "Ok");
}
finally
{
cs.Close();
fsCrypt.Close();
}
return fsIn;
}
但是,当我尝试下载加密文件并保存到用户 Android 画廊时,它无法识别文件路径并抛出错误,指出部分文件路径未找到。我已检查以确保文件路径正确。 (如果我在不加密的情况下上传图像,然后使用下载 url 作为我拥有的图像预览框的来源,它会成功显示图像,因此我推断我正在使用的下载 url 是正确)。
有人能帮忙吗?
解密下载方法如下:
private async void FileDecrypt(string inputFile, string outputFile)
{
var user = await GetUser(localEmail);
FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
fsCrypt.Read(user.Salt, 0, user.Salt.Length);
RijndaelManaged AES = new RijndaelManaged();
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(user.Key, user.Salt, 50000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Padding = PaddingMode.PKCS7;
AES.Mode = CipherMode.CFB;
CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateDecryptor(), CryptoStreamMode.Read);
FileStream fsOut = new FileStream(outputFile, FileMode.Create);
int read;
byte[] buffer = new byte[1048576];
try
{
while ((read = cs.Read(buffer, 0, buffer.Length)) > 0)
{
//Application.DoEvents();
fsOut.Write(buffer, 0, read);
}
}
catch (CryptographicException ex_CryptographicException)
{
DisplayAlert("Error", "CryptographicException error: " + ex_CryptographicException.Message, "Ok");
}
catch (Exception ex)
{
DisplayAlert("Error", "Error: " + ex.Message, "Ok");
}
try
{
cs.Close();
}
catch (Exception ex)
{
DisplayAlert("Error", "Error by closing CryptoStream: " + ex.Message, "Ok");
}
finally
{
fsOut.Close();
fsCrypt.Close();
}
}
private async void BtnDownload_Clicked(object sender, EventArgs e)
{
//output path
string galleryPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures).AbsolutePath;
string outputPath = Path.Combine(galleryPath, localDownloadUrl.FileName);
FileDecrypt(localDownloadUrl.Url, outputPath);
await DisplayAlert("Success", "Image saved to gallery", "OK");
await App.Current.MainPage.Navigation.PopModalAsync();
}
所以,在@Jason 的大力帮助下,我终于解决了这个问题(参考评论)。
在我发布的问题中,FileEncrypt
方法正在获取一个文件(您将其路径作为参数传递给该方法),打开它并使用文件流 fsIn
读取它,使用加密流 cs
对其进行加密,然后使用文件流 fsCrypt 将加密文件写入某个位置。为了将其上传到 Firebase 存储,我将 phone 中某个文件夹的路径传递给写出加密文件的文件流。这导致加密文件被保存到该文件夹中。然后,我将文件流传输到现在保存在我的 phone 中的这个加密文件,并将其作为参数传递给 UploadFile
方法,然后将其上传到 Firebase 存储。方法如下:
private async void FileEncrypt(string inputFile)
{
//this is the path to where the encrypted file will be saved, I have folder named Vault there, I've added the .aes extension so I know it's encrypted.
string galleryPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures).AbsolutePath;
string outputPath = Path.Combine(galleryPath + "/Vault", Path.GetFileName(file.Path) + ".aes");
var user = await GetUser(localEmail);//gets user object (this is my own method)
FileStream fsCrypt = new FileStream(outputPath, FileMode.Create);//used to create the encrypted file
//Set Rijndael symmetric encryption algorithm
RijndaelManaged AES = new RijndaelManaged();
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Padding = PaddingMode.Zeros;
var key = new Rfc2898DeriveBytes(user.Key, user.Salt, 50000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CFB;
// write salt to the beginning of the output file
fsCrypt.Write(user.Salt, 0, user.Salt.Length);
CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write);//used to encrypt the contents of your file
FileStream fsIn = new FileStream(inputFile, FileMode.Open);//used to read your file
//create a buffer (1mb) so only this amount will allocate in the memory and not the whole file
//1048576 is 1MB in binary
byte[] buffer = new byte[1048576];
int read;
try
{
while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
{
cs.Write(buffer, 0, read);
}
fsIn.Close();
}
catch (Exception ex)
{
await DisplayAlert("Error", "Error: " + ex.Message, "Ok");
}
finally
{
cs.Close();
fsCrypt.Close();
}
}
private async void BtnUpload_Clicked(object sender, EventArgs e)
{
//same path as inside the encrypt method
string galleryPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures).AbsolutePath;
string outputPath = Path.Combine(galleryPath + "/Vault", Path.GetFileName(file.Path) + ".aes");
FileEncrypt(file.Path);//file is declared at the top and set in my PickImage method. This will be just be the path to the file you want to encrypt
var user = await GetUser(localEmail);//own method, gets user object which I need to use
FileStream filestream = System.IO.File.OpenRead(outputPath);//get filestream to new encrypted file that we create in File Encrypt method
await firebaseHelper.UploadFile(filestream, Path.GetFileName(file.Path), user.UserID);//upload the file
var downloadurl = await firebaseHelper.GetFile(Path.GetFileName(file.Path), user.UserID);//get the download url link for this file we just uploaded, own method
await firebaseHelper.UploadURL(Path.GetFileName(file.Path), downloadurl.ToString(), user.UserID);//own method, I do this so that I can retrieve the download url, along with user id and original file name easily later on
await DisplayAlert("Success", "Uploaded", "OK");
imgChoosed.Source = "";//this is just an Image preview box
}
public async Task<string> UploadFile(FileStream fileStream, string fileName, Guid userid)
{
try
{
var fileAlreadyExists = await GetFile(fileName, userid);
if (fileAlreadyExists == null)
{
try
{
//this is main upload to firebase storage bit
var imageurl = await firebaseStorage
.Child("Media")
.Child(fileName + userid)
.PutAsync(fileStream);
return imageurl;
}
catch (Exception e)
{
Debug.WriteLine($"Error:{e}");
return null;
}
}
else
{
//below code never gets used, firebase already recognises it is duplicate and appends a number to the filename, prevents duplicates
try
{
var imageurl = await firebaseStorage
.Child("Media")
.Child(fileName + Guid.NewGuid() + userid)
.PutAsync(fileStream);
return imageurl;
}
catch (Exception e)
{
Debug.WriteLine($"Error:{e}");
return null;
}
}
}
catch (Exception e)
{
Debug.WriteLine($"Error:{e}");
return null;
}
}
至于解密,大同小异。 Jason 建议我必须这样做的方式。我们从 Firebase Storage 下载加密文件到我们的设备,然后在 FileDecrypt
方法中传递这个加密文件的路径。这是一种 long/odd 的方式,但由于 Xamarin Forms 的限制,我想不出更好的选择。方法如下:
private async void FileDecrypt(string inputFile, string outputFile)
{
var user = await GetUser(localEmail);//own method
FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);//open and read encrypted file
fsCrypt.Read(user.Salt, 0, user.Salt.Length);//read salt as this the first thing we wrote when encrypting
RijndaelManaged AES = new RijndaelManaged();
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Padding = PaddingMode.Zeros;
var key = new Rfc2898DeriveBytes(user.Key, user.Salt, 50000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CFB;
CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateDecryptor(), CryptoStreamMode.Read);//used to decrypt content of the encrypted file
FileStream fsOut = new FileStream(outputFile, FileMode.Create);//used to create your decrypted file to the path you pass in as output file
int read;
byte[] buffer = new byte[1048576];
try
{
while ((read = cs.Read(buffer, 0, buffer.Length)) > 0)
{
fsOut.Write(buffer, 0, read);
}
}
catch (CryptographicException ex_CryptographicException)
{
await DisplayAlert("Error", "CryptographicException error: " + ex_CryptographicException.Message, "Ok");
}
catch (Exception ex)
{
await DisplayAlert("Error", "Error: " + ex.Message, "Ok");
}
try
{
cs.Close();
}
catch (Exception ex)
{
await DisplayAlert("Error", "Error by closing CryptoStream: " + ex.Message, "Ok");
}
finally
{
fsOut.Close();
fsCrypt.Close();
}
}
private async void BtnDownload_Clicked(object sender, EventArgs e)
{
//output path for encrypted file
string galleryPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures).AbsolutePath;
//remove file extension
string filename = localDownloadUrl.FileName;
int index = filename.LastIndexOf(".");
if (index > 0)
{
filename = filename.Substring(0, index);
}
string outputPath = Path.Combine(galleryPath + "/Vault/", filename);
//download encrypted file locally first
using (var client = new WebClient())
{
client.DownloadFile(localDownloadUrl.Url, outputPath);
}
//output path for decrypted file
string galleryPath1 = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures).AbsolutePath;
string outputPath1 = Path.Combine(galleryPath + "/Vault/", localDownloadUrl.FileName);
FileDecrypt(outputPath, outputPath1);
//delete extra file we downloaded
//File.Delete(outputPath);
//to show pics in gallery
MediaScannerConnection.ScanFile(Android.App.Application.Context, new string[] { outputPath1 }, new string[] { "image / jpeg" }, null);
await DisplayAlert("Success", "Image saved to gallery", "OK");
//display image in image preview: TODO: change the way it works
imageView.Source = ImageSource.FromFile(outputPath1);//this is just an image preview box I have, i just set its source to the newly decrypted file so that it displays it
//await App.Current.MainPage.Navigation.PopModalAsync();
}
我正在尝试使用 AES 加密图像并将其上传到 Firebase 存储,然后解密并下载它。我正在使用以下方法:
private async void BtnUpload_Clicked(object sender, EventArgs e)
{
var fileStream = FileEncrypt(file.Path);
var user = await GetUser(localEmail);
await firebaseHelper.UploadFile(fileStream.Result, Path.GetFileName(file.Path), user.UserID);
var downloadurl = await firebaseHelper.GetFile(Path.GetFileName(file.Path), user.UserID);
await firebaseHelper.UploadURL(Path.GetFileName(file.Path), downloadurl.ToString(), user.UserID);
await DisplayAlert("Success", "Uploaded", "OK");
}
private async Task<FileStream> FileEncrypt(string inputFile)
{
var user = await GetUser(localEmail);
FileStream fsCrypt = new FileStream(inputFile + ".aes", FileMode.Create);
//Set Rijndael symmetric encryption algorithm
RijndaelManaged AES = new RijndaelManaged();
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Padding = PaddingMode.PKCS7;
var key = new Rfc2898DeriveBytes(user.Key, user.Salt, 50000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CFB;
// write salt to the begining of the output file
fsCrypt.Write(user.Salt, 0, user.Salt.Length);
CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
//create a buffer (1mb) so only this amount will allocate in the memory and not the whole file
//1048576 is 1MB in binary
byte[] buffer = new byte[1048576];
int read;
try
{
while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
{
//Application.DoEvents(); // -> for responsive GUI, using Task will be better!
cs.Write(buffer, 0, read);
}
//fsIn.Close();//causes error
}
catch (Exception ex)
{
DisplayAlert("Error", "Error: " + ex.Message, "Ok");
}
finally
{
cs.Close();
fsCrypt.Close();
}
return fsIn;
}
但是,当我尝试下载加密文件并保存到用户 Android 画廊时,它无法识别文件路径并抛出错误,指出部分文件路径未找到。我已检查以确保文件路径正确。 (如果我在不加密的情况下上传图像,然后使用下载 url 作为我拥有的图像预览框的来源,它会成功显示图像,因此我推断我正在使用的下载 url 是正确)。
有人能帮忙吗?
解密下载方法如下:
private async void FileDecrypt(string inputFile, string outputFile)
{
var user = await GetUser(localEmail);
FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
fsCrypt.Read(user.Salt, 0, user.Salt.Length);
RijndaelManaged AES = new RijndaelManaged();
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(user.Key, user.Salt, 50000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Padding = PaddingMode.PKCS7;
AES.Mode = CipherMode.CFB;
CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateDecryptor(), CryptoStreamMode.Read);
FileStream fsOut = new FileStream(outputFile, FileMode.Create);
int read;
byte[] buffer = new byte[1048576];
try
{
while ((read = cs.Read(buffer, 0, buffer.Length)) > 0)
{
//Application.DoEvents();
fsOut.Write(buffer, 0, read);
}
}
catch (CryptographicException ex_CryptographicException)
{
DisplayAlert("Error", "CryptographicException error: " + ex_CryptographicException.Message, "Ok");
}
catch (Exception ex)
{
DisplayAlert("Error", "Error: " + ex.Message, "Ok");
}
try
{
cs.Close();
}
catch (Exception ex)
{
DisplayAlert("Error", "Error by closing CryptoStream: " + ex.Message, "Ok");
}
finally
{
fsOut.Close();
fsCrypt.Close();
}
}
private async void BtnDownload_Clicked(object sender, EventArgs e)
{
//output path
string galleryPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures).AbsolutePath;
string outputPath = Path.Combine(galleryPath, localDownloadUrl.FileName);
FileDecrypt(localDownloadUrl.Url, outputPath);
await DisplayAlert("Success", "Image saved to gallery", "OK");
await App.Current.MainPage.Navigation.PopModalAsync();
}
所以,在@Jason 的大力帮助下,我终于解决了这个问题(参考评论)。
在我发布的问题中,FileEncrypt
方法正在获取一个文件(您将其路径作为参数传递给该方法),打开它并使用文件流 fsIn
读取它,使用加密流 cs
对其进行加密,然后使用文件流 fsCrypt 将加密文件写入某个位置。为了将其上传到 Firebase 存储,我将 phone 中某个文件夹的路径传递给写出加密文件的文件流。这导致加密文件被保存到该文件夹中。然后,我将文件流传输到现在保存在我的 phone 中的这个加密文件,并将其作为参数传递给 UploadFile
方法,然后将其上传到 Firebase 存储。方法如下:
private async void FileEncrypt(string inputFile)
{
//this is the path to where the encrypted file will be saved, I have folder named Vault there, I've added the .aes extension so I know it's encrypted.
string galleryPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures).AbsolutePath;
string outputPath = Path.Combine(galleryPath + "/Vault", Path.GetFileName(file.Path) + ".aes");
var user = await GetUser(localEmail);//gets user object (this is my own method)
FileStream fsCrypt = new FileStream(outputPath, FileMode.Create);//used to create the encrypted file
//Set Rijndael symmetric encryption algorithm
RijndaelManaged AES = new RijndaelManaged();
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Padding = PaddingMode.Zeros;
var key = new Rfc2898DeriveBytes(user.Key, user.Salt, 50000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CFB;
// write salt to the beginning of the output file
fsCrypt.Write(user.Salt, 0, user.Salt.Length);
CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write);//used to encrypt the contents of your file
FileStream fsIn = new FileStream(inputFile, FileMode.Open);//used to read your file
//create a buffer (1mb) so only this amount will allocate in the memory and not the whole file
//1048576 is 1MB in binary
byte[] buffer = new byte[1048576];
int read;
try
{
while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
{
cs.Write(buffer, 0, read);
}
fsIn.Close();
}
catch (Exception ex)
{
await DisplayAlert("Error", "Error: " + ex.Message, "Ok");
}
finally
{
cs.Close();
fsCrypt.Close();
}
}
private async void BtnUpload_Clicked(object sender, EventArgs e)
{
//same path as inside the encrypt method
string galleryPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures).AbsolutePath;
string outputPath = Path.Combine(galleryPath + "/Vault", Path.GetFileName(file.Path) + ".aes");
FileEncrypt(file.Path);//file is declared at the top and set in my PickImage method. This will be just be the path to the file you want to encrypt
var user = await GetUser(localEmail);//own method, gets user object which I need to use
FileStream filestream = System.IO.File.OpenRead(outputPath);//get filestream to new encrypted file that we create in File Encrypt method
await firebaseHelper.UploadFile(filestream, Path.GetFileName(file.Path), user.UserID);//upload the file
var downloadurl = await firebaseHelper.GetFile(Path.GetFileName(file.Path), user.UserID);//get the download url link for this file we just uploaded, own method
await firebaseHelper.UploadURL(Path.GetFileName(file.Path), downloadurl.ToString(), user.UserID);//own method, I do this so that I can retrieve the download url, along with user id and original file name easily later on
await DisplayAlert("Success", "Uploaded", "OK");
imgChoosed.Source = "";//this is just an Image preview box
}
public async Task<string> UploadFile(FileStream fileStream, string fileName, Guid userid)
{
try
{
var fileAlreadyExists = await GetFile(fileName, userid);
if (fileAlreadyExists == null)
{
try
{
//this is main upload to firebase storage bit
var imageurl = await firebaseStorage
.Child("Media")
.Child(fileName + userid)
.PutAsync(fileStream);
return imageurl;
}
catch (Exception e)
{
Debug.WriteLine($"Error:{e}");
return null;
}
}
else
{
//below code never gets used, firebase already recognises it is duplicate and appends a number to the filename, prevents duplicates
try
{
var imageurl = await firebaseStorage
.Child("Media")
.Child(fileName + Guid.NewGuid() + userid)
.PutAsync(fileStream);
return imageurl;
}
catch (Exception e)
{
Debug.WriteLine($"Error:{e}");
return null;
}
}
}
catch (Exception e)
{
Debug.WriteLine($"Error:{e}");
return null;
}
}
至于解密,大同小异。 Jason 建议我必须这样做的方式。我们从 Firebase Storage 下载加密文件到我们的设备,然后在 FileDecrypt
方法中传递这个加密文件的路径。这是一种 long/odd 的方式,但由于 Xamarin Forms 的限制,我想不出更好的选择。方法如下:
private async void FileDecrypt(string inputFile, string outputFile)
{
var user = await GetUser(localEmail);//own method
FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);//open and read encrypted file
fsCrypt.Read(user.Salt, 0, user.Salt.Length);//read salt as this the first thing we wrote when encrypting
RijndaelManaged AES = new RijndaelManaged();
AES.KeySize = 256;
AES.BlockSize = 128;
AES.Padding = PaddingMode.Zeros;
var key = new Rfc2898DeriveBytes(user.Key, user.Salt, 50000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CFB;
CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateDecryptor(), CryptoStreamMode.Read);//used to decrypt content of the encrypted file
FileStream fsOut = new FileStream(outputFile, FileMode.Create);//used to create your decrypted file to the path you pass in as output file
int read;
byte[] buffer = new byte[1048576];
try
{
while ((read = cs.Read(buffer, 0, buffer.Length)) > 0)
{
fsOut.Write(buffer, 0, read);
}
}
catch (CryptographicException ex_CryptographicException)
{
await DisplayAlert("Error", "CryptographicException error: " + ex_CryptographicException.Message, "Ok");
}
catch (Exception ex)
{
await DisplayAlert("Error", "Error: " + ex.Message, "Ok");
}
try
{
cs.Close();
}
catch (Exception ex)
{
await DisplayAlert("Error", "Error by closing CryptoStream: " + ex.Message, "Ok");
}
finally
{
fsOut.Close();
fsCrypt.Close();
}
}
private async void BtnDownload_Clicked(object sender, EventArgs e)
{
//output path for encrypted file
string galleryPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures).AbsolutePath;
//remove file extension
string filename = localDownloadUrl.FileName;
int index = filename.LastIndexOf(".");
if (index > 0)
{
filename = filename.Substring(0, index);
}
string outputPath = Path.Combine(galleryPath + "/Vault/", filename);
//download encrypted file locally first
using (var client = new WebClient())
{
client.DownloadFile(localDownloadUrl.Url, outputPath);
}
//output path for decrypted file
string galleryPath1 = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures).AbsolutePath;
string outputPath1 = Path.Combine(galleryPath + "/Vault/", localDownloadUrl.FileName);
FileDecrypt(outputPath, outputPath1);
//delete extra file we downloaded
//File.Delete(outputPath);
//to show pics in gallery
MediaScannerConnection.ScanFile(Android.App.Application.Context, new string[] { outputPath1 }, new string[] { "image / jpeg" }, null);
await DisplayAlert("Success", "Image saved to gallery", "OK");
//display image in image preview: TODO: change the way it works
imageView.Source = ImageSource.FromFile(outputPath1);//this is just an image preview box I have, i just set its source to the newly decrypted file so that it displays it
//await App.Current.MainPage.Navigation.PopModalAsync();
}