I am working a chat application and when when I upload a image with button click then image doesn't received to another device only sender device showing it.
MyButton click code:
public async void Image_Clicked(object sender, EventArgs e)
{
try
{
file = await CrossMedia.Current.PickPhotoAsync(new Plugin.Media.Abstractions.PickMediaOptions
{
CompressionQuality = 50,
PhotoSize = Plugin.Media.Abstractions.PhotoSize.Medium
});
FileName = file.Path;
FileName = FileName.Substring(FileName.LastIndexOf("/") + 1);
var content = new MultipartFormDataContent();
//IFolder rootFolder = await FileSystem.Current.GetFolderFromPathAsync(FileName);
//var filee = await rootFolder.GetFileAsync(filename2);
//Stream stream = await filee.OpenAsync(FileAccess.Read);
content.Add(new StreamContent(file.GetStream()),
"\"file\"",
$"\"{file.Path}\"");
byteData = Model.Convert.ToByteArray(FileName);
var im = ImageSource.FromStream(this.file.GetStream);
using (var memoryStream = new MemoryStream())
{
activityIndicator.IsRunning = true;
file.GetStream().CopyTo(memoryStream);
file.Dispose();
// return memoryStream.ToArray();
uploadedFilename = await AzureStorage.UploadFileAsync(ContainerType.Image, new MemoryStream(memoryStream.ToArray()));
}
if (!string.IsNullOrWhiteSpace(uploadedFilename))
{
var imageData = await AzureStorage.GetFileAsync(ContainerType.Image, uploadedFilename);
var img = ImageSource.FromStream(() => new MemoryStream(imageData));
TextContainer.Add(new MessageText { imgsource = img });
activityIndicator.IsRunning = false;
}
}
catch( Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
}
}
I am Also using ObservableCollection but unable to get image to second device:
public ObservableCollection<MessageText> TextContainer { get; set; } = new ObservableCollection<MessageText>();
Upload fileCode which I have used to upload my file:
public static async Task<string> UploadFileAsync(ContainerType containerType, Stream stream)
{
var container = GetContainer(containerType);
await container.CreateIfNotExistsAsync();
var name = Guid.NewGuid().ToString();
var fileBlob = container.GetBlockBlobReference(name);
await fileBlob.UploadFromStreamAsync(stream);
return name;
}
I have used SignalR and its working fine for me
Related
I'm trying to add a new function where user can upload images and videos similar to facebook in blazor server .NET 6, I created a new api and followed microsoft documentation of uploading files, Everything is working so far with uploading up to 4 files, but when I'm trying to upload more than 4 it doesn't send a request to the api at all. and after a while it shows these two exceptionsenter image description here enter image description here
Here's the code I'm having: `
private List<File> files = new();
private List<UploadInfo> uploadResults = new();
private int maxAllowedFiles = 10;
private bool shouldRender;
protected override bool ShouldRender() => shouldRender;
private async Task OnInputFileChange(InputFileChangeEventArgs e)
{
shouldRender = false;
long maxFileSize = (long)(4 * Math.Pow(10, 8));
var upload = false;
using var content = new MultipartFormDataContent();
foreach (var file in e.GetMultipleFiles(maxAllowedFiles))
{
if (uploadResults.SingleOrDefault(
f => f.FileName == file.Name) is null)
{
try
{
var fileContent =
new StreamContent(file.OpenReadStream(maxFileSize));
fileContent.Headers.ContentType =
new MediaTypeHeaderValue(file.ContentType);
files.Add(new() { Name = file.Name });
content.Add(
content: fileContent,
name: "\"files\"",
fileName: file.Name);
upload = true;
}
catch (Exception ex)
{
Logger.LogInformation(
"{FileName} not uploaded (Err: 6): {Message}",
file.Name, ex.Message);
uploadResults.Add(
new()
{
FileName = file.Name,
ErrorCode = 6,
Uploaded = false
});
}
}
}
if (upload)
{
var client = ClientFactory.CreateClient();
var response =
await client.PostAsync($"https://localhost:7134/api/Files/FileUpload", content);
if (response.IsSuccessStatusCode)
{
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
};
using var responseStream =
await response.Content.ReadAsStreamAsync();
var newUploadResults = await JsonSerializer
.DeserializeAsync<IList<MediaAPI.UploadInfo>>(responseStream, options);
if (newUploadResults is not null)
{
uploadResults = uploadResults.Concat(newUploadResults).ToList();
}
}
}
shouldRender = true;
}`
When I try to debug it, the debug point disappears when it sends the request:
await client.PostAsync($"https://localhost:7134/api/Files/FileUpload", content);
Anyone has experiansed this issue before?
Thanks in advance.
I have a problem downloading files.
When I download the file, it turns out to be empty, I think that the problem is in the wrong headers, but I could not figure out what exactly.
I have a response body
from controller
But I have empty response arraybuffer
from component
And empty zip downloaded
What am I doing wrong?
request.component.ts
downloadZip() {
this.requestService.downloadZip(this.request.id)
.subscribe((res) => {
const blob = new Blob([res], { type: 'application/zip' });
saveAs(blob, 'Обращение №' + this.request.id + '.zip');
})
}
request.service.ts
downloadZip(requestId: number): Observable<any> {
return this.http.get(this.apiUrl + '/request/downloadZip?id=' + requestId, { responseType: 'arraybuffer'});
}
RequestController.cs
[HttpGet]
[Route("api/request/downloadZip")]
public async Task<IActionResult> DownloadZip(int id)
{
var stream = await _fileStoreService.GetRequestFilesZip(id);
Response.Body = stream;
Response.ContentType = "application/zip";
return Ok();
}
FileStoreService.cs
public async Task<MemoryStream> GetRequestFilesZip(int id)
{
var query = await _db.RequestMedia
.Where(_ => _.RequestId == id)
.ToListAsync();
var fileSharePath = Path.Combine(_configuration["FileTableRootPath"], "RequestFileStore");
var files = new List<string>();
foreach (var media in query)
files.Add(Path.Combine(fileSharePath, media.Hash + Path.GetExtension(WebUtility.HtmlDecode(media.Name))));
var memory = new MemoryStream();
ZipStrings.UseUnicode = true;
using(var zipStream = new ZipOutputStream(memory))
{
zipStream.SetLevel(3);
foreach(var file in files)
{
var entry = new ZipEntry(Path.GetFileName(file))
{
DateTime = DateTime.Now
};
zipStream.PutNextEntry(entry);
var inStream = new MemoryStream();
using var f = new FileStream(file, FileMode.Open, FileAccess.Read);
await f.CopyToAsync(inStream);
inStream.Close();
var content = inStream.ToArray();
await zipStream.WriteAsync(content.AsMemory(0, content.Length));
zipStream.CloseEntry();
}
zipStream.IsStreamOwner = false;
}
memory.Position = 0;
return memory;
}
I changed this
request.service.ts
downloadZip(requestId: number) {
return this.http.get(this.apiUrl + '/request/downloadZip?id=' + requestId, { responseType: 'blob'});
}
and this
RequestController.cs
[HttpGet]
[Route("api/request/downloadZip")]
public async Task<IActionResult> DownloadZip(int id)
{
var stream = await _fileStoreService.GetRequestFilesZip(id);
return new FileStreamResult(stream, "application/zip");
}
Everything works fine
I'm creating a REST API in which accepts a JSON string with 3 different fileUpload in form data.
Here is my API controller post method
public async Task<IHttpActionResult> Post()
{
if (!Request.Content.IsMimeMultipartContent())
{
return StatusCode(HttpStatusCode.UnsupportedMediaType);
}
var filesReadToProvider = await Request.Content.ReadAsMultipartAsync();
var obj = new SubmitReportModel();
var enggCommentImg = new List<FileModel>();
var concernAreaImg = new List<FileModel>();
var remarkImge = new List<FileModel>();
string UploadPath = ("~/Uploads/ReportsData");
Functions.CreateIfMissing(System.Web.Hosting.HostingEnvironment.MapPath(UploadPath));
foreach (var item in filesReadToProvider.Contents)
{
if (item.Headers.ContentDisposition.Name.Contains("jsonKey"))
{
var jsson = await item.ReadAsStringAsync();
obj = Newtonsoft.Json.JsonConvert.DeserializeObject<SubmitReportModel>(jsson);
}
else if (item.Headers.ContentDisposition.Name.Contains("enggCommentImg"))
{
_ = new FileModel();
var fileDataByteArray = await item.ReadAsByteArrayAsync();
FileModel objfile = await SaveFileAsync(fileDataByteArray);
enggCommentImg.Add(objfile);
}
else if (item.Headers.ContentDisposition.Name.Contains("concernAreaImg"))
{
_ = new FileModel();
var fileDataByteArray = await item.ReadAsByteArrayAsync();
FileModel objfile = await SaveFileAsync(fileDataByteArray);
concernAreaImg.Add(objfile);
}
else if (item.Headers.ContentDisposition.Name.Contains("remarkImge"))
{
_ = new FileModel();
var fileDataByteArray = await item.ReadAsByteArrayAsync();
FileModel objfile = await SaveFileAsync(fileDataByteArray);
remarkImge.Add(objfile);
}
}
return Ok();
}
private async Task<FileModel> SaveFileAsync(byte[] fileDataByteArray)
{
string uploadPath = ("~/Uploads/ReportsData");
var objfile = new FileModel();
var filename = uploadPath + "/" + ApiHelper.GetTimestamp() + ".jpg";
using (FileStream fs = new FileStream(System.Web.Hosting.HostingEnvironment.MapPath(filename), FileMode.OpenOrCreate, FileAccess.Write))
{
await fs.WriteAsync(fileDataByteArray, 0, fileDataByteArray.Length).ConfigureAwait(true);
}
objfile.Name = filename;
objfile.Type = "jpg";
return objfile;
}
This API works fine I got JSON plus multiple files in each file object as well.
It works very well when I debug using breakpoints and parse each step using f10. But when I try it without breakpoints, it only saves the first file.
Here is how I'm calling it using Postman:
I tried the same with making it synchronous but still, I get the same result - saving only one file.
Here is my synchronous POST API code
public object Post()
{
if (!Request.Content.IsMimeMultipartContent())
{
return StatusCode(HttpStatusCode.UnsupportedMediaType);
}
//var filesReadToProvider =Request.Content.ReadAsMultipartAsync().GetAwaiter().GetResult();
var filesReadToProvider = Task.Run(async () => await Request.Content.ReadAsMultipartAsync()).Result;
var obj = new SubmitReportModel();
var enggCommentImg = new List<FileModel>();
var concernAreaImg = new List<FileModel>();
var remarkImge = new List<FileModel>();
string UploadPath = ("~/Uploads/ReportsData");
Functions.CreateIfMissing(System.Web.Hosting.HostingEnvironment.MapPath(UploadPath));
foreach (var item in filesReadToProvider.Contents)
{
if (item.Headers.ContentDisposition.Name.Contains("jsonKey"))
{
var jsson = Task.Run(async () => await item.ReadAsStringAsync()).Result;
obj = Newtonsoft.Json.JsonConvert.DeserializeObject<SubmitReportModel>(jsson);
}
else if (item.Headers.ContentDisposition.Name.Contains("enggCommentImg"))
{
_ = new FileModel();
var fileDataByteArray = Task.Run(async () => await item.ReadAsByteArrayAsync()).Result;
if (fileDataByteArray.Length > 0)
{
FileModel objfile = SaveFiles(fileDataByteArray);
enggCommentImg.Add(objfile);
}
}
else if (item.Headers.ContentDisposition.Name.Contains("concernAreaImg"))
{
_ = new FileModel();
var corsrnArr = Task.Run(async () => await item.ReadAsByteArrayAsync()).Result;
if (corsrnArr.Length > 0)
{
FileModel objfile = SaveFiles(corsrnArr);
concernAreaImg.Add(objfile);
}
}
else if (item.Headers.ContentDisposition.Name.Contains("remarkImge"))
{
_ = new FileModel();
var remarkarr = Task.Run(async () => await item.ReadAsByteArrayAsync()).Result;
if (remarkarr.Length > 0)
{
FileModel objfile = SaveFiles(remarkarr);
remarkImge.Add(objfile);
}
}
}
return 1;
}
private FileModel SaveFiles(byte[] fileDataByteArray)
{
string uploadPath = ("~/Uploads/ReportsData");
var objfile = new FileModel();
var filename = uploadPath + "/" + ApiHelper.GetTimestamp() + ".jpg";
using (FileStream fs = new FileStream(System.Web.Hosting.HostingEnvironment.MapPath(filename), FileMode.OpenOrCreate, FileAccess.Write))
{
fs.Write(fileDataByteArray, 0, fileDataByteArray.Length);
}
objfile.Name = filename;
objfile.Type = "jpg";
return objfile;
}
I'm unable to figure what exactly wrong step I made in it as there is no error in it.
UPDATE:
As theGeneral advised, I do recheck all steps and created a log so
found that all images were getting upload within a second so all of
them receive the same timestamp as name, and as a result, only one
file was getting overwrite again and again.
Keeping this thread as it is as this API work for files + other data
(JSON string in my case) and may get helpful for others
I'm uploading a image using Web API.
public IHttpActionResult UploadImage()
{
FileDescription filedescription = null;
var allowedExt=new string[]{".png",".jpg",".jpeg"};
var result = new HttpResponseMessage(HttpStatusCode.OK);
if (Request.Content.IsMimeMultipartContent())
{
Request.Content.LoadIntoBufferAsync().Wait();
var imgTask = Request.Content.ReadAsMultipartAsync<MultipartMemoryStreamProvider>(new MultipartMemoryStreamProvider()).ContinueWith((task) =>
{
MultipartMemoryStreamProvider provider = task.Result;
var content = provider.Contents.ElementAt(0);
Stream stream = content.ReadAsStreamAsync().Result;
Image image = Image.FromStream(stream);
var receivedFileName = content.Headers.ContentDisposition.FileName.Replace("\"", string.Empty);
var getExtension = Path.GetExtension(receivedFileName);
if(allowedExt.Contains(getExtension.ToLower())){
string newFileName = "TheButler" + DateTime.Now.Ticks.ToString() + getExtension;
var originalPath = Path.Combine("Folder Path Here", newFileName);
image.Save(originalPath);
var picture = new Images
{
ImagePath = newFileName
};
repos.ImagesRepo.Insert(picture);
repos.SaveChanges();
filedescription = new FileDescription(imagePath + newFileName, picture.Identifier);
}
});
if (filedescription == null)
{
return ResponseMessage(Request.CreateResponse(HttpStatusCode.InternalServerError, new { message="some error msg."}));
}
else
{
return ResponseMessage(Request.CreateResponse(HttpStatusCode.OK, filedescription));
}
}
else
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, new { message = "This request is not properly formatted" }));
}
}
Above code I have used to save image, But every time filedescription even after image is successfully saved. What's wrong I'm doing here.
I want to return filedescription after image save.
You are using a lot of async methods in the wrong way. You should never make a call to an async method and then wait for it to finish in a synchronous manner (e.g. using Wait() or Result).
If an API exposes an async method, then await for it, turning also the calling method into an async method.
The reason why your filedescription variable is always null, is because you are checking it before you continuation has finished. This is truly a bad practice: if you need a value that is a result of an async operation, then you have to wait for it to finish, but in this case, using the await keyword.
This is the correct way of calling async methods and wait (asynchronously) for them to finish:
public async Task<IHttpActionResult> UploadImage()
{
FileDescription filedescription = null;
var allowedExt = new string[] { ".png", ".jpg", ".jpeg" };
var result = new HttpResponseMessage(HttpStatusCode.OK);
if (Request.Content.IsMimeMultipartContent())
{
await Request.Content.LoadIntoBufferAsync();
var provider = await Request.Content.ReadAsMultipartAsync(new MultipartMemoryStreamProvider());
var content = provider.Contents.ElementAt(0);
Stream stream = await content.ReadAsStreamAsync();
Image image = Image.FromStream(stream);
var receivedFileName = content.Headers.ContentDisposition.FileName.Replace("\"", string.Empty);
var getExtension = Path.GetExtension(receivedFileName);
if (allowedExt.Contains(getExtension.ToLower()))
{
string newFileName = "TheButler" + DateTime.Now.Ticks.ToString() + getExtension;
var originalPath = Path.Combine("Folder Path Here", newFileName);
image.Save(originalPath);
var picture = new Images
{
ImagePath = newFileName
};
repos.ImagesRepo.Insert(picture);
repos.SaveChanges();
filedescription = new FileDescription(imagePath + newFileName, picture.Identifier);
}
if (filedescription == null)
{
return ResponseMessage(Request.CreateResponse(HttpStatusCode.InternalServerError, new { message = "some error msg." }));
}
else
{
return ResponseMessage(Request.CreateResponse(HttpStatusCode.OK, filedescription));
}
}
else
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, new { message = "This request is not properly formatted" }));
}
}
How can I upload an image from a gallery to a server?
I am using FileOpenPicker to pick the image display BitmapImage display in screen. This is working fine at the same time image uploaded to the server. I am using this code to pick the image to gallery using FileOpenPicker.
private async void MenuFlyoutItem_Click(object sender, RoutedEventArgs e)
{
ImagePath = string.Empty;
FileOpenPicker filePicker = new FileOpenPicker();
filePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
filePicker.ViewMode = PickerViewMode.Thumbnail;
// Filter to include a sample subset of file types
filePicker.FileTypeFilter.Clear();
filePicker.FileTypeFilter.Add(".bmp");
filePicker.FileTypeFilter.Add(".png");
filePicker.FileTypeFilter.Add(".jpeg");
filePicker.FileTypeFilter.Add(".jpg");
filePicker.PickSingleFileAndContinue();
view.Activated += viewActivatedddd;
}
private async void viewActivatedddd(CoreApplicationView sender, IActivatedEventArgs args1)
{
FileOpenPickerContinuationEventArgs args = args1 as FileOpenPickerContinuationEventArgs;
if (args != null)
{
if (args.Files.Count == 0) return;
view.Activated -= viewActivatedddd;
StorageFile storageFile = args.Files[0];
var imageFile = args.Files[0] as StorageFile;
var stream = await storageFile.OpenAsync(Windows.Storage.FileAccessMode.Read);
var bitmapImage = new Windows.UI.Xaml.Media.Imaging.BitmapImage();
await bitmapImage.SetSourceAsync(stream);
var decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(stream);
displayImage.Source = bitmapImage;
btnclose.Visibility = Visibility.Visible;
}
}`
Here's my solution when I encountered this issue when leveraging WebAPI.
Convert the image into a memorystream.
Client:
public async Task UploadImage(byte[] image, string url)
{
Stream stream = new System.IO.MemoryStream(image);
HttpStreamContent streamContent = new HttpStreamContent(stream.AsInputStream());
Uri resourceAddress = null;
Uri.TryCreate(url.Trim(), UriKind.Absolute, out resourceAddress);
Windows.Web.Http.HttpRequestMessage request = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.Post, resourceAddress);
request.Content = streamContent;
var httpClient = new Windows.Web.Http.HttpClient();
var cts = new CancellationTokenSource();
Windows.Web.Http.HttpResponseMessage response = await httpClient.SendRequestAsync(request).AsTask(cts.Token);
}
Controller:
public async Task<HttpResponseMessage> Post()
{
Stream requestStream = await this.Request.Content.ReadAsStreamAsync();
byte[] byteArray = null;
using (MemoryStream ms = new MemoryStream())
{
await requestStream.CopyToAsync(ms);
byteArray = ms.ToArray();
}
.
.
.
return Request.CreateResponse(HttpStatusCode.OK);
}