Download file .wav from path API to c# - c#

I have a problem downloading.
Download a file, but with an error when playing, I also notice that the size of the file is doubled.
On one side I have the controller and on the other the function that gets the file
[HttpGet(ApiRoutes.MohC.GetSound)]
public async Task<IActionResult> GetSound([FromRoute] string fileName) {
var memory = await _mohCorpService.GetAudioFile(fileName);
if (memory == null)
return NotFound();
return File(memory, "audio/wav", fileName);
}
/--------------------------------------------------------------------------/
public static async Task<MemoryStream> GetAudioFile(string fileName)
{
string completeFilePath = "/var/www/audio/"+fileName+".wav";
try
{
if (!File.Exists(completeFilePath))
return null;
var memory = new MemoryStream();
using (var stream = new FileStream(completeFilePath, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return memory;
}
catch (Exception e)
{
return null;
}
}

Related

Error while copying content to a stream. IFormFile read Asp.Net

I am trying to read Data from xsls to update my database.
Note: this code is working fine in my local machine .the error comes up only when I publish to server.
the below is the error
{error: "Error while copying content to a stream.",…}
error
:
"Error while copying content to a stream."
exceptionType
:
"System.Net.Http.HttpRequestException"
innerException
:
"Cannot access a disposed object.\r\nObject name: 'System.Net.Http.StreamContent'."
stackTrace
:
" at System.Net.Http.HttpContent.CheckDisposed()\r\n
this my code block
[RequestFormLimits(MultipartBodyLengthLimit = 52428800, ValueLengthLimit = 52428800)]
public async Task<IActionResult> ImportSheet([FromForm] IFormFile uploadedFile)
{
var isClean = await _antimalwareScanService.PostSingleFileResponseAsync(uploadedFile);
if (isClean)
{
if ( uploadedFile is null)
{
return BadRequest();
}
if (!string.IsNullOrEmpty(uploadedFile.FileName))
{
using var stream = uploadedFile.OpenReadStream();
//using var memoryStream = new MemoryStream();
//await stream.CopyToAsync(memoryStream);
using ExcelPackage excel = new(stream);
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelWorkbook workbook = excel.Workbook;
ExcelWorksheets worksheets = workbook.Worksheets;
var psWorksheets = worksheets.FirstOrDefault(x => x.Name.ToLower().Contains("prof services"));
if (psWorksheets != null)
{
await _fileViewModelService.UploadProfServicesFile(psWorksheets);
}
stream.Dispose();
}
}
return Ok();
}
}
you can remove [FromForm] as .net core knows where to get its data from. I have also given you details on how to get it as stream then as byteArray and finally as Base64. You can use whatever works for you.
[HttpPost("File")]
public async Task<IActionResult> ImportSheet(IFormFile uploadedFile)
{
if (uploadedFile.Length > 0)
{
using (var ms = new MemoryStream())
{
await uploadedFile.CopyToAsync(ms);
var fileBytes = ms.ToArray();
string s = Convert.ToBase64String(fileBytes);
}
}
return Ok();
}

Receiving binary Data from a rest endpoint

I am new to API/Rest endpoints, so please forgive my inexperience on this topic.
I am using .net core 3.1. And i have been tasked to write an endpoint, that excepts two parameters a string and a file..
The file will be of binary data (a .bci file format, which i assume is a custom one, but all it is basically is a .txt file, that has been changed to .bci for a machine)
I need to get the file and then read the file using a stringReader and saved to a file locally. Again i am new to endpoints and reading binary data, can anyone help? i have been looking all over the internet today but with no prevail.
I know the below code is incorrect, but really struggling on this one. Any help would much be appreciated.
//GET: api/ProcessResultsFiles]
[HttpGet]
public async Task<IActionResult> ProcessResults(IFormFile file, string bench)
{
await ReadData(file);
return Ok();
}
private static Task<byte[]> ReadData(IFormFile benchNameFile)
{
using (StringReader sr = new StringReader(benchNameFile))
{
string input = null;
while ((input = sr.ReadLine()) != null)
{
Console.WriteLine(input);
}
}
}
From your description, I assume you want to upload the file to the Physical storage/folder, after that might be you want to download the file to local, if that is the case, you could refer the following sample:
[HttpPost("upload")]
public IActionResult Upload(List<IFormFile> formFiles, string subDirectory)
{
try
{
subDirectory = subDirectory ?? string.Empty;
var target = Path.Combine(_environment.WebRootPath, subDirectory);
if(!Directory.Exists(target))
Directory.CreateDirectory(target);
formFiles.ForEach(async file =>
{
if (file.Length <= 0) return;
var filePath = Path.Combine(target, file.FileName);
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
});
return Ok("Upload success!");
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpPost("download")]
public IActionResult DownLoad( string subDirectory, string filename)
{
//Build the File Path.
string path = Path.Combine(_environment.WebRootPath, subDirectory +"/"+ filename);
if (System.IO.File.Exists(path))
{
//Read the File data into Byte Array.
byte[] bytes = System.IO.File.ReadAllBytes(path);
//download the file.
return File(bytes, "application/octet-stream", filename);
}
else
{
return Ok("file not exist");
}
}
The result as below:
More detail information about upload file in asp.net core, you can refer the following articles:
Upload files in ASP.NET Core
Upload And Download Multiple Files Using Web API
From the above articles, when upload file, if you want to save the byte array, you can refer the following code:
public async Task<IActionResult> OnPostUploadAsync()
{
using (var memoryStream = new MemoryStream())
{
await FileUpload.FormFile.CopyToAsync(memoryStream);
// Upload the file if less than 2 MB
if (memoryStream.Length < 2097152)
{
var file = new AppFile()
{
Content = memoryStream.ToArray()
};
_dbContext.File.Add(file);
await _dbContext.SaveChangesAsync();
}
else
{
ModelState.AddModelError("File", "The file is too large.");
}
}
return Page();
}

ASP.NET Core 5 web api duplicates file name on save

I have an API written in asp.net core 5. There I have a controller that receive a IFile object. Everything is fine till I need on the end of the process to save the file on the local hard drive. There my path named formatedPath is correct and it contains the full path (like: ‪D:/tanulmanyiversenyek.hu/server/profile/8226dfa5-2743aiE2-45cfpTjG-b186yENr-167280a987aa.png).
But when the save is called I god an exception with error message:
D:\tanulmanyiversenyek.hu\server\profile of the filename ‪D:/tanulmanyiversenyek.hu/server/profile/8226dfa5-2743aiE2-45cfpTjG-b186yENr-167280a987aa.png
The bolder part is added somehow. I can't figure out why.
[Route("api/v{version:apiVersion}/image/profile")]
[ApiVersion(ApplicationSettingsConstans.ActiveVersion)]
[HttpPost]
[AllowAnonymous]
[ProducesResponseType((int)HttpResponseType.OK, Type = typeof(string))]
[ProducesResponseType((int)HttpResponseType.BadRequest)]
[Produces("application/json")]
public async Task<string> UploadProfileImageAsync([FromForm] IFormFile file)
{
ServiceResponse<string> request = await _imageUploadService.UploadProfileImageAsync(file);
if (!request.IsSuccess)
{
throw new Exception(request.Message);
}
return request.ResultObject;
}
public async Task<ServiceResponse<string>> UploadProfileImageAsync(IFormFile file)
{
ServiceResponse<string> response = new ServiceResponse<string>();
try
{
response.ResultObject = await ImageUploadHandler.SaveProfileImageAsync(file);
}
catch (Exception ex)
{
response.IsSuccess = false;
response.Message = ex.Message;
response.ResultObject = string.Empty;
}
return response;
}
public static async Task<string> SaveProfileImageAsync(IFormFile file)
{
if (file.Length < 1)
{
return null;
}
string result = string.Empty;
string extension = file.FileName.Reverse().Split(".")[0].Reverse();
string fileName = $"{GenerateName()}.{extension}";
string subFolder = UploadedFileType.Profile.ToString().ToLower();
#if DEBUG
string path = $#"{ServerPathEnviorement.Base()}\{subFolder}\{fileName}";
result = $#"\{subFolder}\{fileName}";
#else
string path = $#"{ServerPathEnviorement.Base()}/{subFolder}/{fileName}";
result = $#"/{subFolder}/{fileName}";
#endif
await SaveOnDisk(path, file, 720, 405);
return result;
}
private static async Task SaveOnDisk(string path, IFormFile file, int width = 1920, int height = 1080)
{
string formatedPath = path.Replace(#"/", #"\");
Image image = null;
using (MemoryStream memoryStream = new MemoryStream())
{
await file.CopyToAsync(memoryStream);
image = Image.FromStream(memoryStream);
}
using (Bitmap bitmap = new Bitmap(image))
{
byte[] data = ImageCompressor.ScaleImage(bitmap, width, height, false);
using (MemoryStream memoryStream = new MemoryStream(data))
{
image = Image.FromStream(memoryStream);
image.Save(formatedPath, ImageFormat.Jpeg); *//error thrown here*
}
}
The same error appears form Postman or from my react app.
Interesting think is if I repleace the formatedPath variable with direct path to file like: d:/tanulmanyiversenyek.hu/server/profile/167280a987aa.png it is working !

Issue in disposing Stream objects for asp.net mvc application?

I have asp.net mvc application which has file upload functionality. While uploading the file, I am performing few validations on the uploaded content before moving it to database and file system location.
Here goes my code:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddImage([Bind(Include = "image,ImageName,ImageType,CountryId,Keyword,Source,Copyright,Description")] CreateImageViewModel model)
{
if (!this.ModelState.IsValid)
{
return View("Images");
}
if (model != null && model.image.ContentType.Contains(Constants.Image) && !ValidateUploadedImageContent(model.image, model.image.FileName))
{
var dto = new ImageDTO();
model.FilePath = model.image.FileName;
dto.ImageFile = model.image;
dto.Name = model.ImageName;
dto.FilePath = model.image.FileName;
dto.FileType = Path.GetExtension(model.FilePath);
dto.ImageType = model.ImageType;
dto.CountryId = model.CountryId;
dto.Keyword = model.Keyword;
dto.Source = model.Source;
dto.Copyright = model.Copyright;
dto.Description = model.Description;
dto.CreatedBy = UserDto.emailId;
try
{
_imageService.SaveImage(dto);
}
catch (Exception ex)
{
if (ex.Message.Equals(Constants.InvalidImageType))
return GetSafeRedirect(Url.Action("AddImage", model) + "#onload-errors");
throw ex;
}
return RedirectToAction(Constants.Actions.Images.ToString());
}
else
{
return GetSafeRedirect(Url.Action("AddImage", model) + "#onload-errors");
}
}
private bool ValidateUploadedImageContent(HttpPostedFileBase uploadedFile, string imageFileName)
{
if (Path.GetExtension(imageFileName).Equals(".svg", StringComparison.OrdinalIgnoreCase))
{
if (uploadedFile.ContentLength > 0)
{
byte[] data;
//using (Stream inputStream = uploadedFile.InputStream)
//{
Stream inputStream = uploadedFile.InputStream;
var memoryStream = inputStream as MemoryStream;
if (memoryStream == null)
{
memoryStream = new MemoryStream();
inputStream.CopyTo(memoryStream);
}
data = memoryStream.ToArray();
//}
var parsedData = Encoding.UTF8.GetString(data, 0, data.Length).TrimEnd('\0');
var result = parsedData.ContainsAny(Constants.InsecureStrings, StringComparison.CurrentCultureIgnoreCase);
return result;
}
}
return false;
}
Here in the above method: ValidateUploadedImageContent(), I tried to dispose the stream object with the help of using statement but I found that if I keep the below code in the method: ValidateUploadedImageContent(), then in that case post validation process, I found on debugging that the ContentLength property is set with 0 value and finally corrupted image gets saved in the file system location.
Updated :
private bool ValidateUploadedImageContent(HttpPostedFileBase uploadedFile, string imageFileName)
{
if (Path.GetExtension(imageFileName).Equals(".svg", StringComparison.OrdinalIgnoreCase))
{
if (uploadedFile.ContentLength > 0)
{
byte[] data;
using (Stream inputStream = uploadedFile.InputStream)
{
Stream inputStream = uploadedFile.InputStream;
var memoryStream = inputStream as MemoryStream;
if (memoryStream == null)
{
memoryStream = new MemoryStream();
inputStream.CopyTo(memoryStream);
}
data = memoryStream.ToArray();
}
var parsedData = Encoding.UTF8.GetString(data, 0, data.Length).TrimEnd('\0');
var result = parsedData.ContainsAny(Constants.InsecureStrings, StringComparison.CurrentCultureIgnoreCase);
return result;
}
}
return false;
}
Can anyone help me to know how to fix this issue?
First to address your issue, which I now understand is that after the call to ValidateUploadedImageContent the image stream is invalid.
That is because the stream gained from the HttpPostedFileBase is "read-only sequential (non-seekable)" as detailed in this SO answer. This explains why the stream's ContentLength is 0 - the stream has been consumed by the validation call.
If you have flexibility with the ImageDTO class, modifying the validation method such that it returns the image bytes would be a workaround.
For example,
// on success, buffer contains the image data. Otherwise it is null.
private bool ValidateUploadedImageContent(
out byte[] buffer,
HttpPostedFileBase uploadedFile,
string imageFileName)
{
buffer = null;
if (Path.GetExtension(imageFileName).Equals(".svg", StringComparison.OrdinalIgnoreCase))
{
if (uploadedFile.ContentLength > 0)
{
var reader = new BinaryReader(inputStream);
buffer = reader.ReadBytes((int)uploadedFile.ContentLength);
var parsedData = Encoding.UTF8.GetString(buffer, 0, buffer.Length).TrimEnd('\0');
return parsedData.ContainsAny(Constants.InsecureStrings, StringComparison.CurrentCultureIgnoreCase);
}
}
return false;
}
I've used BinaryReader to simplify the code.
Then back to the calling method,
byte[] imageBuffer = null;
if (model != null && model.image.ContentType.Contains(Constants.Image)
&& !ValidateUploadedImageContent(out imageBuffer, model.image, model.image.FileName)) {
var dto = new ImageDTO();
using(var imageStream = new MemoryStream(imageBuffer)) {
// pass along imageStream to your ImageDTO and save.
}
}
Again, hopefully you have some flexibility with the ImageDTO class.

Windows Phone 8 - reading and writing in an existing txt file in the project

Hi i'm stucked in a problem, i created a txt file that i put on the app. I'm trying to read from it the content that i write on it before. With that code:
public async Task WriteDataToFileAsync(string fileName, string content)
{
byte[] data = Encoding.Unicode.GetBytes(content);
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.CreateFileAsync(fileName,CreationCollisionOption.ReplaceExisting);
using (var s = await file.OpenStreamForWriteAsync())
{
await s.WriteAsync(data, 0, data.Length);
}
}
public async Task<string> ReadFileContentsAsync(string fileName)
{
var folder = ApplicationData.Current.LocalFolder;
try
{
var file = await folder.OpenStreamForReadAsync(fileName);
using (var streamReader = new StreamReader(file))
{
return streamReader.ReadToEnd();
}
}
catch (Exception)
{
MessageBox.Show("Error");
return string.Empty;
}
}
private async void functionWhereNeedReeding()
{
string contents = await this.ReadFileContentsAsync("myimportedfile.txt");
MessageBox.Show(contents);
}
Give me all times the message of error and i can't understand where is my mistake. Hoping that you'll help me. For sure contents is still empty.
I created a helper function in my WP 7 project recently, to read a text file included in the project. You can try to use it, the function also working in WP 8 project :
public static class FileHelper
{
public static string ReadFile(string filePath)
{
var ResrouceStream = Application.GetResourceStream(new Uri(filePath, UriKind.Relative));
if (ResrouceStream != null)
{
Stream myFileStream = ResrouceStream.Stream;
if (myFileStream.CanRead)
{
StreamReader myStreamReader = new StreamReader(myFileStream);
return myStreamReader.ReadToEnd();
}
}
return "";
}
}
Then I can use that function this way (in this example the file resides under Assets folder) :
var textFileContent = FileHelper.ReadFile(#"Assets\MyTextFile.txt");

Categories

Resources