i am trying to resize an image using the WebImage helper BEFORE uploading to Azure blob, using the following code, but getting this error:
cannot convert from 'system.web.helpers.webimage' to 'system.io.stream'
The code is as follows:
public async Task<string> UploadPropertyImageAsync(HttpPostedFileBase imageToUpload)
{
string imageFullPath = null;
if (imageToUpload == null || imageToUpload.ContentLength == 0 || imageToUpload.ContentLength >= 8388608)
{
return null;
}
//Image img = System.Drawing.Image.FromStream(imageToUpload);
WebImage img = new WebImage(imageToUpload.InputStream);
if (img.Width > 1000)
img.Resize(1000, 1000);
try
{
CloudStorageAccount cloudStorageAccount = ConnectionString.GetConnectionString();
CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference("property");
if (await cloudBlobContainer.CreateIfNotExistsAsync())
{
await cloudBlobContainer.SetPermissionsAsync(
new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
}
);
}
string imageName = Guid.NewGuid().ToString() + "-" + Path.GetExtension(img.FileName);
CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(imageName);
cloudBlockBlob.Properties.ContentType = img.ContentType;
await cloudBlockBlob.UploadFromStreamAsync(img);
Any idea where i'm going wrong?
CloudBlockBlob.UploadFromStreamAsync expects a stream which your WebImage object is not and hence you're getting this error.
What you would need to do is convert the image into a stream. I looked up the documentation and there's no direct method to do so.
However you can get the bytes from the WebImage using WebImage.GetBytes and then use CloudBlockBlob.UploadFromByeArrayAsync method to upload that byte array as blob in Azure Storage.
The exception is pretty self explanatory.
This line is expecting a Stream, not a WebImage variable.
await cloudBlockBlob.UploadFromStreamAsync(img);
There are plenty of examples showing how to upload files to Azure, for example:
Uploading to Azure
... and here...
An Introduction to Windows Azure BLOB Storage
Related
I have two questions:
1.When i use postman to upload an image, for example when i browse 15.jpg, it generates something like nDt3Vxjca/15.jpg in value column link
what is nDt3Vxjca.
public async Task<IActionResult> Upload([FromForm] IFormFileViewModel request)
{
var requestContent = new MultipartFormDataContent();
if (request.image!= null)
{
byte[] data;
using (var br = new BinaryReader(request.image.OpenReadStream()))
{
data = br.ReadBytes((int)request.image.OpenReadStream().Length);
}
ByteArrayContent bytes = new ByteArrayContent(data);
requestContent.Add(bytes, "image", request.image.FileName);
};
var client = _httpClientFactory.CreateClient();
string clientID = "abcdefg";
client.DefaultRequestHeaders.Add("Authorization", "Client-ID " + clientID);
var response = await client.PostAsync("https://api.imgur.com/3/upload", requestContent);
return Ok();
}
I copy a some lines of code to convert IformFile to binary. It still manages to upload the image but it doesn't point to my account, it returns something like this:
{"status":200,"success":true,"data":{"id":"I5oGuBd","deletehash":"qVwP3BONUUU9dr7","account_id":null,"account_url":null,"ad_type":null
account_id and account_url is null, Did i make mistake somewhere?
I have the following two methods that handles taking photos from a camera and picking photos from a library. They're both similar methods as at the end of each method, I get an ImageSource back from the Stream and I pass it onto another page which has an ImageSource binding ready to be set. These two method work perfectly. The next step now is to save the Image in SQLite so I can show the images in a ListView later on. My question for the XamGods (Xamarin Pros =), what is the best way to save image in SQLite in 2019? I have been in the forums for hours and I still don't have a tunnel vision on what I want to do. I can either
Convert Stream into an array of bytes to save in Sqlite.
Convert ImageSource into an array of bytes (messy/buggy).
Somehow retrieve the actual Image selected/taken and convert that into an array of bytes into SQLite
I'm sorry if my question is general, but Xamarin does not provide a clear-cut solution on how to save images in SQLite and you can only find bits and pieces of solutions throughout the forums listed below.
How to save and retrieve Image from Sqlite
Load Image from byte[] array.
Creating a byte array from a stream
Thank you in advance!
private async Task OnAddPhotoFromCameraSelected()
{
Console.WriteLine("OnAddPhotoFromCameraSelected");
var photo = await Plugin.Media.CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions() { });
var stream = photo.GetStream();
photo.Dispose();
if (stream != null)
{
ImageSource cameraPhotoImage = ImageSource.FromStream(() => stream);
var parms = new NavigationParameters();
parms.Add("image", cameraPhotoImage);
var result = await NavigationService.NavigateAsync("/AddInspectionPhotoPage?", parameters: parms);
if (!result.Success)
{
throw result.Exception;
}
}
}
private async Task OnAddPhotoFromLibrarySelected()
{
Console.WriteLine("OnAddPhotoFromLibrarySelected");
Stream stream = await DependencyService.Get<IPhotoPickerService>().GetImageStreamAsync();
if (stream != null)
{
ImageSource selectedImage = ImageSource.FromStream(() => stream);
var parms = new NavigationParameters();
parms.Add("image", selectedImage);
parms.Add("stream", stream);
var result = await NavigationService.NavigateAsync("/AddInspectionPhotoPage?", parameters: parms);
if (!result.Success)
{
throw result.Exception;
}
}
}
As Jason said that you can save image path into sqlite database, but if you still want to save byte[] into sqlite database, you need to convert stream into byte[] firstly:
private byte[] GetImageBytes(Stream stream)
{
byte[] ImageBytes;
using (var memoryStream = new System.IO.MemoryStream())
{
stream.CopyTo(memoryStream);
ImageBytes = memoryStream.ToArray();
}
return ImageBytes;
}
Then load byte[] from sqlite, converting into stream.
public Stream BytesToStream(byte[] bytes)
{
Stream stream = new MemoryStream(bytes);
return stream;
}
For simple sample, you can take a look:
Insert byte[] in sqlite:
private void insertdata()
{
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "sqlite1.db3");
using (var con = new SQLiteConnection(path))
{
Image image = new Image();
image.Content = ConvertStreamtoByte();
var result = con.Insert(image);
sl.Children.Add(new Label() { Text = result > 0 ? "insert successful insert" : "fail insert" });
}
}
Loading image from sqlite:
private void getdata()
{
var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "sqlite1.db3");
using (var con = new SQLiteConnection(path))
{
var image= con.Query<Image>("SELECT content FROM Image ;").FirstOrDefault();
if(image!=null)
{
byte[] b = image.Content;
Stream ms = new MemoryStream(b);
image1.Source = ImageSource.FromStream(() => ms);
}
}
}
Model:
public class Image
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string FileName { get; set; }
public byte[] Content { get; set; }
}
I am using asp.net webforms.
I have pdfs in Azure storage that I need to process. I am using PDFJet library in order to do that.
I would like to
stream the pdf without downloading it as I have to process a large number of pdfs.
I am using the following function to stream the pdfs from Azure:
public MemoryStream DownloadToMemoryStream(DTO.BlobUpload b)
{
CloudStorageAccount storageAccount = Conn.SNString(b.OrgID);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(b.Container);
CloudBlockBlob blob = container.GetBlockBlobReference(b.FileName);
var sasToken = blob.GetSharedAccessSignature(new SharedAccessBlobPolicy()
{
Permissions = SharedAccessBlobPermissions.Read,
SharedAccessExpiryTime = DateTime.UtcNow.AddMinutes(10),//assuming the blob can be downloaded in 10 miinutes
}, new SharedAccessBlobHeaders()
{
ContentDisposition = "attachment; filename=file-name"
});
using (MemoryStream ms = new MemoryStream())
{
blob.DownloadToStream(ms);
return ms;
}
}
And in the aspx.cs page the following code to read the pdf stream:
BufferedStream pdfScript = new BufferedStream(new FileStream(ScriptPath + Script, FileMode.Open));
SortedDictionary<Int32, PDFobj> objects = pdfFinalScript.Read(pdfScript);
However I get the error message: Cannot access a closed Stream
If I download the pdf to disk, this is the function I use, this work but it is not practical:
blockBlob.DownloadToFile(b.LocalPath + b.FileName, FileMode.Create);
BufferedStream pdfScript = new BufferedStream(new FileStream(ScriptPath + Script, FileMode.Open));
Thank you for your help.
Cannot access a closed Stream
According to error information, it indicates that you need to reset stream position.
Please have a try to reset the stream position before return it.
blob.DownloadToStream(ms);
ms.Position = 0; //add this code
return ms;
Updated:
ms was closed if out of using section. So please have a try to use the following code.
MemoryStream stream = new MemoryStream();
using (MemoryStream ms = new MemoryStream())
{
blob.DownloadToStream(ms);
ms.Position = 0
ms.CopyTo(stream);
stream.Position = 0;
return stream;
}
I have server part on Asp.net core which receives a file in Content-Type: multipart/form-data format header and send it to azure blob storage in a stream. But when I'm sending file about 200 MB and more I have an error
“The request body is too large and exceeds the maximum permissible limit”
as I searched it could happen in the old version of WindowsAzure.Storage but I have version 9.1.1. And as I looked deeper method UploadFromStreamAsync chank blob on 4 MB by default. So I don't know what to only to ask your help.
My controller:
public async Task<IActionResult> Post(string folder)
{
string azureBlobConnectionString = _configuration.GetConnectionString("BlobConnection");
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(azureBlobConnectionString);
HttpResponseUploadClass responseUploadClass = await Request.StreamFile(folder, storageAccount);
FormValueProvider formModel = responseUploadClass.FormValueProvider;
var viewModel = new MyViewModel();
var bindingSuccessful = await TryUpdateModelAsync(viewModel, prefix: "",
valueProvider: formModel);
if (!bindingSuccessful)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
}
return Ok(responseUploadClass.Url);
}
And class where i send stream filestream to azure blob
public static async Task<HttpResponseUploadClass> StreamFile(this HttpRequest request, string folder, CloudStorageAccount blobAccount)
{
CloudBlobClient blobClient = blobAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(folder);
CloudBlockBlob blockBlob = null;
if (!MultipartRequestHelper.IsMultipartContentType(request.ContentType))
{
throw new Exception($"Expected a multipart request, but got {request.ContentType}");
}
var formAccumulator = new KeyValueAccumulator();
var boundary = MultipartRequestHelper.GetBoundary(
MediaTypeHeaderValue.Parse(request.ContentType),
DefaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, request.Body);
var section = await reader.ReadNextSectionAsync();
while (section != null)
{
ContentDispositionHeaderValue contentDisposition;
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);
var disposition = ContentDispositionHeaderValue.Parse(section.ContentDisposition);
if (hasContentDispositionHeader)
{
if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
{
try
{
string fileName = HttpUtility.UrlEncode(disposition.FileName.Value.Replace("\"", ""), Encoding.UTF8);
blockBlob = container.GetBlockBlobReference(Guid.NewGuid().ToString());
blockBlob.Properties.ContentType = GetMimeTypeByWindowsRegistry(fileName);
blockBlob.Properties.ContentDisposition = "attachment; filename*=UTF-8''" + fileName;
await blockBlob.UploadFromStreamAsync(section.Body);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
else if (MultipartRequestHelper.HasFormDataContentDisposition(contentDisposition))
{
var key = HeaderUtilities.RemoveQuotes(contentDisposition.Name);
var encoding = GetEncoding(section);
using (var streamReader = new StreamReader(
section.Body,
encoding,
detectEncodingFromByteOrderMarks: true,
bufferSize: 1024,
leaveOpen: true))
{
var value = await streamReader.ReadToEndAsync();
if (String.Equals(value, "undefined", StringComparison.OrdinalIgnoreCase))
{
value = String.Empty;
}
formAccumulator.Append(key.Value, value);
if (formAccumulator.ValueCount > DefaultFormOptions.ValueCountLimit)
{
throw new InvalidDataException($"Form key count limit {DefaultFormOptions.ValueCountLimit} exceeded.");
}
}
}
}
section = await reader.ReadNextSectionAsync();
}
var formValueProvider = new FormValueProvider(
BindingSource.Form,
new FormCollection(formAccumulator.GetResults()),
CultureInfo.CurrentCulture);
return new HttpResponseUploadClass{FormValueProvider = formValueProvider, Url = blockBlob?.Uri.ToString()};
}
As you have said, each block blob can be a different size, up to a maximum of 100 MB (4 MB for requests using REST versions before 2016-05-31), and a block blob can include up to 50,000 blocks.
If you are writing a block blob that is no more than 256 MB (64 MB for requests using REST versions before 2016-05-31) in size, you can upload it in its entirety with a single write operation, see Put Blob.
Storage clients default to a 32 MB maximum single block upload, settable using the SingleBlobUploadThresholdInBytes property.
When a block blob upload is larger than the value in this property, storage clients break the file into blocks.
You can set the number of threads used to upload the blocks in parallel using the ParallelOperationThreadCount property.
BlobRequestOptions requestoptions = new BlobRequestOptions()
{
SingleBlobUploadThresholdInBytes = 1024 * 1024 * 50, //50MB
ParallelOperationThreadCount = 12,
};
CloudStorageAccount account = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
CloudBlobClient blobclient = account.CreateCloudBlobClient();
blobclient.DefaultRequestOptions = requestoptions;
CloudBlobContainer blobcontainer = blobclient.GetContainerReference("uploadfiles");
blobcontainer.CreateIfNotExists();
CloudBlockBlob blockblob = blobcontainer.GetBlockBlobReference("bigfiles");
For more details, you could refer to this thread.
Is there a way to read an embedded JSON file in a PCL project with PCLStorage module? I looked everywhere but couldn't find a sample related to this matter.
EDIT: PCLStorage link: https://github.com/dsplaisted/pclstorage
you need something like this:
public static async Task<string> ReadFileContent(string fileName, IFolder rootFolder)
{
ExistenceCheckResult exist = await rootFolder.CheckExistsAsync(fileName);
string text = null;
if (exist == ExistenceCheckResult.FileExists)
{
IFile file = await rootFolder.GetFileAsync(fileName);
text = await file.ReadAllTextAsync();
}
return text;
}
to use:
IFolder rootFolder = FileSystem.Current.LocalStorage;
IFolder myCoolFolder = await rootFolder.CreateFolderAsync("MyCoolForler", CreationCollisionOption.OpenIfExists);
string fileContent = await this.ReadFileContent("MyCoolFile.txt", myCoolFolder);
You should be able to read embedded resources like this:
var assembly = typeof(LoadResourceText).GetTypeInfo().Assembly;
Stream stream = assembly.GetManifestResourceStream("WorkingWithFiles.PCLTextResource.txt");
string text = "";
using (var reader = new System.IO.StreamReader (stream)) {
text = reader.ReadToEnd ();
}
Xamarin has a great guide on how to work with them here.
https://developer.xamarin.com/guides/cross-platform/xamarin-forms/working-with/files/