Saving bitmap to gallery in Android - c#

I thought that should be simple, yet I can't figure it out.
I keep getting the error: System.IO.DirectoryNotFoundException: Could not find a part of the path "/storage/emulated/0/Pictures/Screenshots/name.jpg".
The code:
string root = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures).Path;
File myDir = new File(root + "/Screenshots");
myDir.Mkdirs();
string timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").Format(new Date());
string fname = CommunicationHandler.GetNickname() + "|" + timeStamp + ".jpg";
File file = new File(myDir, fname);
if (file.Exists())
file.Delete();
try
{
using (System.IO.Stream outStream = System.IO.File.Create(file.Path))
{
finalBitmap.Compress(Bitmap.CompressFormat.Jpeg, 100, outStream);
outStream.Flush();
outStream.Close();
}
}
catch (Exception e)
{
Toast.MakeText(Activity, e.ToString(), ToastLength.Long).Show();
}
Also, I can't access manually to /storage/emulated/0..
Why can't I manage to save the bitmap to my phone gallery? What's the problem in the code above?

If you want to create a new directory, you can use System.IO.Directory.CreateDirectory(root); to create it.
//create a directory called MyCamera
string root = Environment.GetExternalStoragePublicDirectory(Environment.DirectoryDcim).ToString() + "/MyCamera/";
//create the Directory
System.IO.Directory.CreateDirectory(root);

As taken from here:
MediaScannerConnection.scanFile(this, new String[]{file.toString()}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
}
Also, note that you could just add an image to the gallery via a simple line:
MediaStore.Images.Media.insertImage(applicationContext.getContentResolver(), IMAGE ,"nameofimage" , "description");

Related

A generic error occured in GDI+ while saving image

I have to save an image in post request in byte64String format
when i save that image i get A generic error occurred in GDI+
here is my code
byte[] ix = Convert.FromBase64String(obj.Image);
var ID = obj.Id;
using (var mStream = new MemoryStream(ix))
{
var img = Image.FromStream(mStream);
var image = obj.ImageName + ".jpg";
string path = HostingEnvironment.MapPath("/Images/" + ImageType + "/" + ID + "/" + image);
System.IO.Directory.CreateDirectory(path);
try
{
img.Save(path, System.Drawing.Imaging.ImageFormat.Jpeg);
}
catch (Exception e)
{
var d = e;
}
}
also
this is not a permission issue as i am able to create text files in the same directory
Quite simply you are confusing paths and filenames.
The problem if could hazzard a guess, you probably have a folder that is your filename, and you are trying to save a file with that same name, which windows forbids
Your code tweaked
var image = $"{obj.ImageName }.jpg";
// get the path, and only the path
string path = HostingEnvironment.MapPath($"/Images/{ImageType}/{ID}/");
// Create directory if needed (from that path)
Directory.CreateDirectory(path,image);
...
// now create the correct full path
var fullPath = Path.Combine(path,fileName);
// save
img.Save(fullPath, ImageFormat.Jpeg);

How to force a download of a created file to a users computer c#

I am looking to allow a person to to export journal entries into a text file. I can create a file with all the data but rather strictly saving the file somewhere specific I want to allow a user to download and save the file where they want on their computer. How to I force a download of a file after I create it with StreamWriter. I currently have the following code:
string fileName = "Journal.txt";
using (StreamWriter journalExport = new StreamWriter(fileName))
{
foreach (JournalEntryView entry in journalEnteries)
{
//write each journal entery to file/document
journalExport.WriteLine(entry.timestamp + " - " + entry.author + " (" + entry.authorRole + ")");
journalExport.WriteLine(entry.text);
journalExport.WriteLine("");
journalExport.WriteLine("");
}
}
I am also trying to put this into an ActionResult and return the file.
EDIT:
The following code is my new current code and the direction I am looking to go in, but when I use an ActionLink to call this method, i just get redirected to a new page rather than downloading the file.
string fileName = "Journal.txt";
string filepath = ConfigurationManager.AppSettings["DocumentRoot"] + "\\" + id + "\\" + fileName;
using (StreamWriter journalExport = new StreamWriter(filepath))
{
foreach (JournalEntryView entry in journalEnteries)
{
//write each journal entery to file/document
journalExport.WriteLine(entry.timestamp + " - " + entry.author + " (" + entry.authorRole + ")");
journalExport.WriteLine(entry.text);
journalExport.WriteLine("");
journalExport.WriteLine("");
}
}
byte[] fileData = System.IO.File.ReadAllBytes(filepath);
string contentType = MimeMapping.GetMimeMapping(filepath);
var cd = new System.Net.Mime.ContentDisposition
{
FileName = fileName,
Inline = true,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(fileData, contentType);
This might be what you are looking for:
public ActionResult GetFile()
{
...processing stuff...
return File("/files/file.pdf", "application/pdf");
//or
return File("/files/file.pdf", "application/force-download", "donwloadname.pdf");
}

ExternalException: A generic error occurred in GDI+

I am using Selenium WebDriver in C# and
I am trying to dynamically create a folder and save screenshots of failing tests to it.
Here I am running the group of test cases (Test Suite of 66 test cases).
After running the test suite I found few failed tests with GDI+ error and were not captured as a screenshot.
But when I run them individually most of the failed cases (GDI+ error) were passing except few.
Here is the code for creating a folder:
TestExecutionStartTime = DateTime.Now;
baseDirectory = AppDomain.CurrentDomain.BaseDirectory + #"\" + ConfigurationManager.AppSettings.GetValues("failedTests")[0];
Browser = ConfigurationManager.AppSettings["WebDriver"];
DirectoryInfo directory = new DirectoryInfo(baseDirectory);
DirectoryInfo[] subdirs = directory.GetDirectories();
if (System.IO.Directory.GetDirectories(baseDirectory).Length == 0)
{
screenshotDirectory = baseDirectory + #"\" + (DateTime.Now.ToString("yyyy_MM_dd_hh_mm") + "_" + Browser);
Directory.CreateDirectory(screenshotDirectory);
}
Here is the code for taking screenshot:
public void takeScreenshot(string filename)
{
string fname = filename + ".jpg";
string screenshot = screenshotDirectory + #"\" + fname;
Screenshot ss = ((ITakesScreenshot)WebDriver).GetScreenshot();
byte[] image = ss.AsByteArray;
using (MemoryStream ms = new MemoryStream(image))
{
Image i = Image.FromStream(ms);
i.Save(screenshot);
}
I assume that the error is at this i.Save(screenshot) call, but I was not able to resolve it.
I have reason to believe (from experience) that your issue comes about as a result of the stream being destroyed while it is being saved (the using statement).
Things to be aware of:
Write permissions wherever you are saving the image
Make sure the path is correct - this will throw a GDI+ exception and is very misleading, verify your path, try a temporary directory instead of creating your custom image directory to rule this one out.
Make sure the height of the image is not bigger than (65534px)
You can verify this by looking at the size:
var bitmapTemp = new Bitmap(stream);
Console.WriteLine(bitmapTemp.Height);
Here's some code that destroys the stream only after the image is saved:
public static Screenshot GetScreenshot(ChromeDriver driver)
{
Screenshot ss = ((ITakesScreenshot)driver).GetScreenshot();
return ss;
}
public static void SaveScreenshot(byte[] byteArray, string location)
{
var stream = new MemoryStream(byteArray);
var img = Image.FromStream(stream);
img.Save(location);
stream.Dispose();
}
And use the functions like so:
var path = AppDomain.CurrentDomain.BaseDirectory;
var ss = GetScreenshot(driver);
SaveScreenshot(ss.AsByteArray, path + "imagename.jpg");
Thanks for your inputs AntonB.
I have considered your points and tried differently and got the solution.
i have used [SetUpFixture], [OneTimeSetUp] and [OneTimeTearDown] to create folder only once and it solved the problem.
Here is the code:
[SetUpFixture]
public class Config
{
public Config()
{
}
public string baseDirectory;
public static string screenshotDirectory;
[OneTimeSetUp]
public void SetUp()
{
Console.WriteLine("Creating a folder to capture failed scenarios");
baseDirectory = AppDomain.CurrentDomain.BaseDirectory + #"\" + ConfigurationManager.AppSettings.GetValues("failedTests")[0];
string Browser = ConfigurationManager.AppSettings["WebDriver"];
screenshotDirectory = baseDirectory + #"\" + (DateTime.Now.ToString("yyyy_MM_dd_hh_mm") + "_" + Browser);
Directory.CreateDirectory(screenshotDirectory);
}
[OneTimeTearDown]
public void TearDown()
{
}
}

I can read and write from a txt file internal storage (documents folder) but cannot browse to that location because it doesn't exist

Alright so I've managed to read/write files programatically in C# in Xamarin Studio. And it's working on my device.
However, when I output the exact path that the file is being written to, to the console, that path doesn't even exist anywhere in the entire phone!!!!
How is that?
using System;
using System.IO;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
namespace ToolbarSample
{
[Activity(Label = "ToolbarSample", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
string content = "Jason rules";
string filename = "file.txt";
var documents = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
// Get our button from the layout resource,
// and attach an event to it
Button button = FindViewById<Button>(Resource.Id.button);
TextView viewer = FindViewById<TextView>(Resource.Id.textView1);
if (File.Exists(documents + #"/" + filename))
{
string newContent = File.ReadAllText(documents + #"/" + filename);
if (viewer != null)
{
viewer.Text = newContent;
Console.WriteLine("File exists in: " + documents + #"/" + filename);
}
}
if (button != null)
{
button.Click += delegate
{
button.Enabled = false;
if (!Directory.Exists(documents))
{
viewer.Text = "Directory not found: " + documents;
}
else
{
Console.WriteLine("Directory exists.");
File.WriteAllText(documents + #"/" + filename, content);
if (!File.Exists(documents + #"/" + filename))
{
viewer.Text = "File not found: " + documents + #"/" + filename;
}
else
{
string newContent = File.ReadAllText(documents + #"/" + filename);
if (viewer != null)
{
viewer.Text = newContent;
Console.WriteLine("File exists in: " + documents + #"/" + filename);
}
}
}
};
}
}
}
}
The following gets outputted to the console upon successful read from internal sdcard:
Directory exists. File exists in:
/data/data/ToolbarSample.ToolbarSample/files/file.txt
But using (many different) file managers - all with root access - and hidden files being shown - I cannot navigate to that path because it does not exist. I even did a whole phone search for "file.txt" and not a single result showed up. Yet I am able to read that file whenever I open my app and click the button.
The file at the location you have specified does exist. You cannot access that location from your PC via USB and File Explorer, but you can access the location (and the file) if you use a good File Manager app like Root Explorer.
If you really want your users to be able to access these saved files, I'd suggest that you save these files to a better location so that the user can easily transfer files from their phone to the computer via USB.
It quite simple both Read/Write data from File .
public String ReadFileData()
{
var path = global::Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var filename = Path.Combine(path.ToString(), "loginSystem.txt");
String line;
objData = new List<UsersData>();
// Read the file and display it line by line.
StreamReader file = new StreamReader(filename);
while ((line = file.ReadLine()) != null)
{
string[] words = line.Split(',');
if (words.Length != 1)
objData.Add(new UsersData(words[0], words[1], words[2]));
}
file.Close();
return String.Empty;
}
Save data into file
private string SaveDataToSd(String FirstName, String Address, String Password)
{
var path = global::Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var filename = Path.Combine(path.ToString(), "loginSystem.txt");
String contents = FirstName + "," + Password + "," + Address;
try
{
using (StreamWriter data_file = new StreamWriter(filename, true))
{
data_file.WriteLine(contents);
}
return contents;
}
catch (Exception ex)
{
RunOnUiThread(() =>
{
var builder = new AlertDialog.Builder(this);
builder.SetMessage(ex.InnerException + "Saving file went wrong");
builder.SetTitle("Unable to save file");
builder.Show();
});
return String.Empty;
}
}

Image uploading in images folder issue in Asp.net

I am trying to upload JPG file to a folder I have created in my project.
The image does not get saved in the images folder. It displays my image when I upload but the image itself is not present in images folder.
Here is the code i am using:
private void btnUpload_Click(object sender, System.EventArgs e)
{
// Initialize variables
string sSavePath;
string sThumbExtension;
int intThumbWidth;
int intThumbHeight;
// Set constant values
sSavePath = "images/";
sThumbExtension = "_thumb";
intThumbWidth = 160;
intThumbHeight = 120;
// If file field isn’t empty
if (filUpload.PostedFile != null)
{
// Check file size (mustn’t be 0)
HttpPostedFile myFile = filUpload.PostedFile;
int nFileLen = myFile.ContentLength;
if (nFileLen == 0)
{
lblOutput.Text = "No file was uploaded.";
return;
}
// Check file extension (must be JPG)
if (System.IO.Path.GetExtension(myFile.FileName).ToLower() != ".jpg")
{
lblOutput.Text = "The file must have an extension of JPG";
return;
}
// Read file into a data stream
byte[] myData = new Byte[nFileLen];
myFile.InputStream.Read(myData,0,nFileLen);
// Make sure a duplicate file doesn’t exist. If it does, keep on appending an
// incremental numeric until it is unique
string sFilename = System.IO.Path.GetFileName(myFile.FileName);
int file_append = 0;
while (System.IO.File.Exists(Server.MapPath(sSavePath + sFilename)))
{
file_append++;
sFilename = System.IO.Path.GetFileNameWithoutExtension(myFile.FileName)
+ file_append.ToString() + ".jpg";
}
// Save the stream to disk
System.IO.FileStream newFile
= new System.IO.FileStream(Server.MapPath(sSavePath + sFilename),
System.IO.FileMode.Create);
newFile.Write(myData,0, myData.Length);
newFile.Close();
// Check whether the file is really a JPEG by opening it
System.Drawing.Image.GetThumbnailImageAbort myCallBack =
new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
Bitmap myBitmap;
try
{
myBitmap = new Bitmap(Server.MapPath(sSavePath + sFilename));
// If jpg file is a jpeg, create a thumbnail filename that is unique.
file_append = 0;
string sThumbFile = System.IO.Path.GetFileNameWithoutExtension(myFile.FileName)
+ sThumbExtension + ".jpg";
while (System.IO.File.Exists(Server.MapPath(sSavePath + sThumbFile)))
{
file_append++;
sThumbFile = System.IO.Path.GetFileNameWithoutExtension(myFile.FileName) +
file_append.ToString() + sThumbExtension + ".jpg";
}
// Save thumbnail and output it onto the webpage
System.Drawing.Image myThumbnail
= myBitmap.GetThumbnailImage(intThumbWidth,
intThumbHeight, myCallBack, IntPtr.Zero);
myThumbnail.Save (Server.MapPath(sSavePath + sThumbFile));
imgPicture.ImageUrl = sSavePath + sThumbFile;
// Displaying success information
lblOutput.Text = "File uploaded successfully!";
// Destroy objects
myThumbnail.Dispose();
myBitmap.Dispose();
}
catch (ArgumentException errArgument)
{
// The file wasn't a valid jpg file
lblOutput.Text = "The file wasn't a valid jpg file.";
System.IO.File.Delete(Server.MapPath(sSavePath + sFilename));
}
}
}
public bool ThumbnailCallback()
{
return false;
}
I'd be surprised if the line myThumbnail.Save (Server.MapPath(sSavePath + sThumbFile)); works...
You are trying to map a file which doesn't exist yet!
Try
myThumbnail.Save(Server.MapPath(sSavePath) + sThumbFile));

Categories

Resources