I have an image displayed in an Image Control and I need to save that Image using FileSavePicker
This is what I have done:
Dim fileSavePicker As New FileSavePicker()
fileSavePicker.FileTypeChoices.Add("PNG", New String() {".png"})
fileSavePicker.FileTypeChoices.Add("JPG", New String() {".jpg"})
fileSavePicker.FileTypeChoices.Add("BMP", New String() {".bmp"})
fileSavePicker.FileTypeChoices.Add("TIFF", New String() {".tiff"})
fileSavePicker.FileTypeChoices.Add("EXIF", New String() {".exif"})
fileSavePicker.FileTypeChoices.Add("ICO", New String() {".ico"})
Dim saveFile As StorageFile = Await fileSavePicker.PickSaveFileAsync()
If saveFile IsNot Nothing Then
//Here I need to save that Image
End If
It is saving the image but with "0 KB" and showing me the blank Image.
What should I be doing?
Edit:
This is the error I'm getting:
SaveToFile is not a memeber of Windows.UI.XAML.Media.Imaging.WriteableBitmap'.
And similarly for 'Load'
Edit:
This is how I am trying to load image:
Private Async Sub Scenario1Button_Click(sender As Object, e As RoutedEventArgs) Handles Scenario1Button.Click
Image1.Visibility = Windows.UI.Xaml.Visibility.Visible
LayoutRoot.Visibility = Windows.UI.Xaml.Visibility.Collapsed
grdImages.Visibility = Windows.UI.Xaml.Visibility.Collapsed
Dim openPicker As New FileOpenPicker
openPicker.ViewMode = PickerViewMode.List
openPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary
openPicker.FileTypeFilter.Add("*")
Dim files As IReadOnlyList(Of StorageFile) = Await openPicker.PickMultipleFilesAsync
If files.Count > 0 Then
'Application now has read/write access to the picked file(s)
For Each file In files
Dim stream = Await file.OpenAsync(Windows.Storage.FileAccessMode.Read)
Dim image As New BitmapImage()
image.SetSource(stream)
Image1.Source = image
LayoutRoot.Visibility = Windows.UI.Xaml.Visibility.Collapsed
Next file
Else
End If
End Sub
According to the documentation:
When the call to this method completes successfully, it returns a storageFile object that was created to represent the saved file. The file name, extension, and location of this storageFile match those specified by the user, but the file has no content.
To save the content of the file, your app must write the content to this storageFile.
So you get a storage file and you need to write to it.
Saving a BitmapImage is not possible, so you would need to start off by loading the image into a WriteableBitmap. If you are just copying the original file - you can just load it to a stream and save it back to the new storage file. If you want to go the WriteableBitmap route - here is a set of extension methods you could use to load/save the image if you used C#:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.Graphics.Imaging;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Media.Imaging;
namespace Xyzzer.WinRT.Extensions
{
public static class WriteableBitmapSaveExtensions
{
public static async Task<WriteableBitmap> Load(string relativePath)
{
return await new WriteableBitmap(1, 1).Load(relativePath);
}
public static async Task<WriteableBitmap> Load(this WriteableBitmap writeableBitmap, string relativePath)
{
var storageFile = await Package.Current.InstalledLocation.GetFileAsync(relativePath.Replace('/', '\\'));
return await writeableBitmap.Load(storageFile);
}
public static async Task<WriteableBitmap> Load(this WriteableBitmap writeableBitmap, StorageFile storageFile)
{
var stream = await storageFile.OpenReadAsync();
var wb = new WriteableBitmap(1, 1);
wb.SetSource(stream);
return wb;
}
public static async Task SaveToFile(this WriteableBitmap writeableBitmap)
{
await writeableBitmap.SaveToFile(
KnownFolders.PicturesLibrary,
string.Format(
"{0}_{1}.png",
DateTime.Now.ToString("yyyyMMdd_HHmmss_fff"),
Guid.NewGuid()));
}
public static async Task SaveToFile(this WriteableBitmap writeableBitmap, StorageFolder storageFolder)
{
await writeableBitmap.SaveToFile(
storageFolder,
string.Format(
"{0}_{1}.png",
DateTime.Now.ToString("yyyyMMdd_HHmmss_fff"),
Guid.NewGuid()));
}
public static async Task SaveToFile(this WriteableBitmap writeableBitmap, StorageFolder storageFolder, string fileName)
{
StorageFile outputFile = await storageFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
Guid encoderId;
var ext = Path.GetExtension(fileName);
if (new[] { ".bmp", ".dib" }.Contains(ext))
{
encoderId = BitmapEncoder.BmpEncoderId;
}
else if (new[] { ".tiff", ".tif" }.Contains(ext))
{
encoderId = BitmapEncoder.TiffEncoderId;
}
else if (new[] { ".gif" }.Contains(ext))
{
encoderId = BitmapEncoder.TiffEncoderId;
}
else if (new[] { ".jpg", ".jpeg", ".jpe", ".jfif", ".jif" }.Contains(ext))
{
encoderId = BitmapEncoder.TiffEncoderId;
}
else if (new[] { ".hdp", ".jxr", ".wdp" }.Contains(ext))
{
encoderId = BitmapEncoder.JpegXREncoderId;
}
else //if (new [] {".png"}.Contains(ext))
{
encoderId = BitmapEncoder.PngEncoderId;
}
await writeableBitmap.SaveToFile(outputFile, encoderId);
}
public static async Task SaveToFile(this WriteableBitmap writeableBitmap, StorageFile outputFile, Guid encoderId)
{
try
{
Stream stream = writeableBitmap.PixelBuffer.AsStream();
byte[] pixels = new byte[(uint)stream.Length];
await stream.ReadAsync(pixels, 0, pixels.Length);
int offset;
for (int row = 0; row < (uint)writeableBitmap.PixelHeight; row++)
{
for (int col = 0; col < (uint)writeableBitmap.PixelWidth; col++)
{
offset = (row * (int)writeableBitmap.PixelWidth * 4) + (col * 4);
byte B = pixels[offset];
byte G = pixels[offset + 1];
byte R = pixels[offset + 2];
byte A = pixels[offset + 3];
// convert to RGBA format for BitmapEncoder
pixels[offset] = R; // Red
pixels[offset + 1] = G; // Green
pixels[offset + 2] = B; // Blue
pixels[offset + 3] = A; // Alpha
}
}
IRandomAccessStream writeStream = await outputFile.OpenAsync(FileAccessMode.ReadWrite);
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(encoderId, writeStream);
encoder.SetPixelData(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Premultiplied, (uint)writeableBitmap.PixelWidth, (uint)writeableBitmap.PixelHeight, 96, 96, pixels);
await encoder.FlushAsync();
await writeStream.GetOutputStreamAt(0).FlushAsync();
}
catch (Exception ex)
{
string s = ex.ToString();
}
}
}
}
Related
I have tried the following code ..
When I try out the following code I get 404 content not found. Also my controller doesn't get hit when I try to debug the code ..
public async Task<IActionResult> Download(string filename)
{
if (filename == null)
return Content("filename not present");
var path = Path.Combine(Directory.GetCurrentDirectory(),"wwwroot", filename);
var memory = new MemoryStream();
using (var stream = new FileStream(path, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return File(memory, GetContentType(path), Path.GetFileName(path));
}
Upload file with size and filename as response:
public async Task<IActionResult> OnPostUploadAsync(IFormFile file)
{
long size = file.Length;//in bytes
if (file.Length > 0)
{
var name = Path.GetRandomFileName();
//var fileOriginName = file.FileName;
var path = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "wwwroot", name);
using (var stream = System.IO.File.Create(path))
{
await file.CopyToAsync(stream);
}
return Ok(new { size = size, filename = name });
}
else {
return Ok(new { size = 0, filename = ""});
}
}
===============================================
I have an api like below and I had a file test.txt in wwwroot folder.
public async Task<IActionResult> Download(string filename)
{
if (filename == null)
return Content("filename not present");
var path = Path.Combine(System.IO.Directory.GetCurrentDirectory(), "wwwroot", filename);
var memory = new MemoryStream();
using (var stream = new FileStream(path, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
var contentType = "APPLICATION/octet-stream";
return File(memory, contentType, Path.GetFileName(path));
}
Then when I call localhost:port/home/download?filename=test then I'll get exception that file can't find. And when I call localhost:port/home/Download?filename=test.txt it succeeds.
My API is in an asp.net core MVC project and I think you need to check the contentType.
i'm using xamarin.forms app and need to save file(it this situation pdf file). This is my scenario: I'm using media plugin to save images with camera and from that images with PdfDocument object i generate PDF file:
PdfDocument document = new PdfDocument();
for (int i = 0; i < Images.Count(); i++)
{
PdfPage page = document.Pages.Add();
PdfGraphics graphics = page.Graphics;
Stream imageStream = Images.ElementAt(i);
PdfBitmap image = new PdfBitmap(imageStream);
page.Graphics.DrawImage(image, new PointF(40, 100));
}
MemoryStream stream = new MemoryStream();
document.Save(stream);
document.Close(true);
String localPath =
Task.Run(() => DependencyService.Get<ISave>().SaveFile(stream, "test.pdf")).Result;
And everything is working fine, its generates me pdf document with pages stream is filled with bytes, and the problem is in this SaveFile:
[assembly: Dependency(typeof(Save))]
namespace PdfSave.Droid.Shared
{
public class Save: ISave
{
private readonly string _rootDir = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "TestFolder");
public async Task<string> SaveFile(Stream pdfStream, string fileName)
{
if (!Directory.Exists(_rootDir))
Directory.CreateDirectory(_rootDir);
var filePath = Path.Combine(_rootDir, fileName);
using (var memoryStream = new MemoryStream())
{
await pdfStream.CopyToAsync(memoryStream);
File.WriteAllBytes(filePath, memoryStream.ToArray());
}
return filePath;
}
}
the problem is in this line
await pdfStream.CopyToAsync(memoryStream);
the memory stream is empty! . Anyone know what should might be the problem?
I want to set image.Source via async stream in an UWP application. Otherwise the image will flicker when switch to other image source.
My code is as below. And the log shows it works. Certainly I put 2 image files in the corresponding path before I test the demo code.
But in fact I did not see any picture shown, why?
Log:
111111111111 image file path = C:\Users\tomxu\AppData\Local\Packages\a0ca0192-f41a-43ca-a3eb-f128a29b00c6_1qkk468v8nmy0\LocalState\2.jpg
22222222222
33333333333333
4444444444444
The thread 0x6d38 has exited with code 0 (0x0).
The thread 0x6a34 has exited with code 0 (0x0).
111111111111 image file path = C:\Users\tomxu\AppData\Local\Packages\a0ca0192-f41a-43ca-a3eb-f128a29b00c6_1qkk468v8nmy0\LocalState\1.jpg
22222222222
33333333333333
4444444444444
Code:
private async void setImageSource(string imageFilePath)
{
StorageFile sFile = await StorageFile.GetFileFromPathAsync(imageFilePath);
Debug.WriteLine("111111111111 image file path = " + imageFilePath);
Stream fileStream = await sFile.OpenStreamForReadAsync();
Debug.WriteLine("22222222222");
InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream();
Debug.WriteLine("33333333333333");
await fileStream.CopyToAsync(ras.AsStreamForRead());
Debug.WriteLine("4444444444444");
BitmapImage bi = new BitmapImage();
bi.SetSource(ras);
image1.Source = bi;
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
string fullFolder = ApplicationData.Current.LocalFolder.Path;
if (count % 2 == 1)
{
setImageSource(fullFolder + #"\1.jpg");
//image1.Source = new BitmapImage(new Uri(#"ms-appx:///Assets/1.jpg"));
}
else
{
setImageSource(fullFolder + #"\2.jpg");
//image1.Source = new BitmapImage(new Uri(#"ms-appx:///Assets/2.jpg"));
}
count++;
}
Here is an example of how I convert a base64 image string to a BitmapImage..
var ims = new InMemoryRandomAccessStream();
var bytes = Convert.FromBase64String(base64String);
var dataWriter = new DataWriter(ims);
dataWriter.WriteBytes(bytes);
await dataWriter.StoreAsync();
ims.Seek(0);
var img = new BitmapImage();
img.SetSource(ims);
ims.Dispose();
return img;
Try some of the things I'm doing there. Like I notice your code is not setting the seek of the InMemoryReadAccessStream
For your question, I have something to clarify with you.
Your pictures are always in the application data folder. If you want to show it at runtime by programming, the easy way is using the ms-appdata URI scheme to refer to files that come from the app's local, roaming, and temporary data folders. Then, you could use this URL to initialize the BitmapImage object. With this way, you don't need to manually manipulate the file stream.
private void setImageSource(int i)
{
BitmapImage bi = new BitmapImage(new Uri("ms-appdata:///local/"+i+".png"));
image1.Source = bi;
}
private int count = 0;
private void Button_Click(object sender, RoutedEventArgs e)
{
if (count % 2 == 1)
{
setImageSource(1);
}
else
{
setImageSource(2);
}
count++;
}
If you say you have to manipulate the file stream to initialize the BitmaImage, then please add some break points to debug your code. If you add break points to check the InMemoryRandomAccessStream after call CopyToAsync method, you will see that its size is 0. It meant that the file stream has not been wrote to it. To solve this issue, you need to set a buffer size for it. Note: you used ras.AsStreamForRead() method, it's incorrect. You're writing stream to it, so you need to call ras.AsStreamForWrite().
The code looks like the following:
private async void setImageSource(string imageFilePath)
{
StorageFile sFile = await StorageFile.GetFileFromPathAsync(imageFilePath);
using (Stream fileStream = await sFile.OpenStreamForReadAsync())
{
using (InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream())
{
await fileStream.CopyToAsync(ras.AsStreamForWrite((int)fileStream.Length));
ras.Seek(0);
BitmapImage bi = new BitmapImage();
bi.SetSource(ras);
img.Source = bi;
}
}
}
private int count = 0;
private void Button_Click(object sender, RoutedEventArgs e)
{
string fullFolder = ApplicationData.Current.LocalFolder.Path;
if (count % 2 == 1)
{
setImageSource(fullFolder + #"\1.jpg");
}
else
{
setImageSource(fullFolder + #"\2.jpg");
}
count++;
}
In addition, like #visc said, you need to call ras.Seek(0) method to reset the stream to beginning, else the image will not show there.
We have to rework how we're sending emails since we are using Amazon SES. In the past, we were using smtp but can't do that in this case. The class that needs updated has taken in a MailMessage object and used smtp to send it. So I'm trying to rework the method to be able to continue to accept the MailMessage object and convert it to a MimeKit MimeMessage. For the most part it's working fine except when it comes to attachments. In the code I have, the attachment gets added and sent, however, when trying to open it appears it's corrupted or something. In my test case I attached a csv file. I could not open it in excel after receiving the email.
public class EmailAbstraction
{
public virtual void Send(MailMessage mailMessage)
{
sendMessage(mailMessage);
}
private static void sendMessage(MailMessage mailMessage)
{
using (var client = new AmazonSimpleEmailServiceClient(AwsConstants.SESAWSKey, AwsConstants.SESAWSSecret, AwsConstants.RegionEndpoint))
{
foreach (var to in mailMessage.To)
{
using (var messageStream = new MemoryStream())
{
var newMessage = new MimeMessage();
var builder = new BodyBuilder
{
HtmlBody = mailMessage.Body
};
newMessage.From.Add(mailMessage.From == null
? new MailboxAddress(EmailConstants.DefaultFromEmailDisplayName, EmailConstants.DefaultFromEmailAddress)
: new MailboxAddress(mailMessage.From.Address));
newMessage.To.Add(new MailboxAddress(to.DisplayName, to.Address));
newMessage.Subject = mailMessage.Subject;
foreach (var attachment in mailMessage.Attachments)
{
builder.Attachments.Add(attachment.Name, attachment.ContentStream);
}
newMessage.Body = builder.ToMessageBody();
newMessage.WriteTo(messageStream);
var request = new SendRawEmailRequest
{
RawMessage = new RawMessage { Data = messageStream }
};
client.SendRawEmail(request);
}
}
}
}
}
And in my test app, I have this.
internal class Program
{
private static void Main(string[] args)
{
var s = GetFileStream();
var m = new MailMessage();
var sender = new MailAddress("info#ourwebsite.com", "info");
m.From = sender;
m.Sender = sender;
m.Body = "test email";
m.Subject = "test subject";
m.To.Add(myemail);
m.Attachments.Add(new Attachment(s, "test-file.csv"));
new EmailAbstraction().Send(m);
}
private static MemoryStream GetFileStream()
{
var stream = new MemoryStream();
var fileStream = File.Open(#"C:\Users\dev\Desktop\test-file.csv", FileMode.Open);
fileStream.CopyTo(stream);
fileStream.Close();
return stream;
}
}
This is just copied from the MimeKit source code:
static MimePart GetMimePart (System.Net.Mail.AttachmentBase item)
{
var mimeType = item.ContentType.ToString ();
var contentType = ContentType.Parse (mimeType);
var attachment = item as System.Net.Mail.Attachment;
MimePart part;
if (contentType.MediaType.Equals ("text", StringComparison.OrdinalIgnoreCase))
part = new TextPart (contentType);
else
part = new MimePart (contentType);
if (attachment != null) {
var disposition = attachment.ContentDisposition.ToString ();
part.ContentDisposition = ContentDisposition.Parse (disposition);
}
switch (item.TransferEncoding) {
case System.Net.Mime.TransferEncoding.QuotedPrintable:
part.ContentTransferEncoding = ContentEncoding.QuotedPrintable;
break;
case System.Net.Mime.TransferEncoding.Base64:
part.ContentTransferEncoding = ContentEncoding.Base64;
break;
case System.Net.Mime.TransferEncoding.SevenBit:
part.ContentTransferEncoding = ContentEncoding.SevenBit;
break;
//case System.Net.Mime.TransferEncoding.EightBit:
// part.ContentTransferEncoding = ContentEncoding.EightBit;
// break;
}
if (item.ContentId != null)
part.ContentId = item.ContentId;
var stream = new MemoryStream ();
item.ContentStream.CopyTo (stream);
stream.Position = 0;
part.Content = new MimeContent (stream);
return part;
}
Error while uploading file method in Client Object Model + Sharepoint 2010. Once the file got uploaded. After that though the code compiles with no error
I get the error while executing
"{"Value does not fall within the expected range."}
{System.Collections.Generic.SynchronizedReadOnlyCollection}
I have a method which takes care of functionality to upload files
///////////////////////////////////////////////////////////////////////////////////////////
public void Upload_Click(string documentPath, byte[] documentStream)
{
String sharePointSite = "http://cvgwinbasd003:28838/sites/test04";
String documentLibraryUrl = sharePointSite +"/"+ documentPath.Replace('\\','/');
////////////////////////////////////////////////////////////////////
//Get Document List
List documentsList = clientContext.Web.Lists.GetByTitle("Doc1");
var fileCreationInformation = new FileCreationInformation();
//Assign to content byte[] i.e. documentStream
fileCreationInformation.Content = documentStream;
//Allow owerwrite of document
fileCreationInformation.Overwrite = true;
//Upload URL
fileCreationInformation.Url = documentLibraryUrl;
Microsoft.SharePoint.Client.File uploadFile = documentsList.RootFolder.Files.Add(
fileCreationInformation);
//uploadFile.ListItemAllFields.Update();
clientContext.ExecuteQuery();
}
/////////////////////////////////////////////////////////////////////////////////////////////////
In the MVC 3.0 application in the controller I have defined the following method to invoke the upload method.
//////////////////////////////////////////////////////////////////////////////////////////////////
public ActionResult ProcessSubmit(IEnumerable<HttpPostedFileBase> attachments)
{
System.IO.Stream uploadFileStream=null;
byte[] uploadFileBytes;
int fileLength=0;
foreach (HttpPostedFileBase fileUpload in attachments)
{
uploadFileStream = fileUpload.InputStream;
fileLength=fileUpload.ContentLength;
}
uploadFileBytes= new byte[fileLength];
uploadFileStream.Read(uploadFileBytes, 0, fileLength);
using (DocManagementService.DocMgmtClient doc = new DocMgmtClient())
{
doc.Upload_Click("Doc1/Doc2/Doc2.1/", uploadFileBytes);
}
return RedirectToAction("SyncUploadResult");
}
//////////////////////////////////////////////////////////////////////////////////////////////////
Please help me to locate the error
I think your documentLibraryUrl needs to be relative. This is working for me with Sharepoint 2013
[HttpPost]
[ValidateAntiForgeryToken]
[SharePointContextFilter]
public ActionResult Upload()
{
if (Request.Files.Count > 0)
{
HttpPostedFileBase file = Request.Files[0];
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
using (var clientContext = spContext.CreateUserClientContextForSPHost())
{
if (clientContext != null)
{
FileCreationInformation newFile = new FileCreationInformation();
using (MemoryStream ms = new MemoryStream())
{
file.InputStream.CopyTo(ms);
byte[] array = ms.GetBuffer();
newFile.Content = array;
}
List docs = clientContext.Web.Lists.GetByTitle("Documents");
Folder folder = docs.RootFolder;
clientContext.Load(folder);
clientContext.ExecuteQuery();
newFile.Url = docs.RootFolder.ServerRelativeUrl + "/" + fileName;
Microsoft.SharePoint.Client.File uploadFile = docs.RootFolder.Files.Add(newFile);
clientContext.Load(uploadFile);
clientContext.ExecuteQuery();
//Set the metadata
Microsoft.SharePoint.Client.ListItem item = uploadFile.ListItemAllFields;
string docTitle = string.Empty;
item["Title"] = docTitle;
item.Update();
clientContext.ExecuteQuery();
}
}
}
}
return RedirectToAction("Index", new { SPHostUrl = SharePointContext.GetSPHostUrl(HttpContext.Request).AbsoluteUri });
}