I'm learning C# with blazor, I wanted to know how I can validate an input of type file, so that it doesn't allow files larger than 3MB
This example explains how to upload files(in svg format) in Blazor with the InputFile component. Pay attention to the variable maxFileSize that set the maximum number of bytes that can be supplied by the Stream.
FileUpload.razor.cs
private bool fileUploading;
private string filePath = "C:\\fileFolder\\file.svg";
private const int maxFileSize= 3 * 1024 * 1024; //3MB max size
private async Task UploadSvgFileAsync(InputFileChangeEventArgs e)
{
fileUploading = true;
try
{
string fileExtension = Path.GetExtension(e.File.Name);
if (!fileExtension.Equals(".svg", StringComparison.OrdinalIgnoreCase))
throw new Exception("SVG file is required.");
var stream = e.File.OpenReadStream(maxFileSize);
await using FileStream fs = new(filePath, FileMode.Create);
await stream.CopyToAsync(fs);
}
catch (Exception ex)
{
//some error handling
}
fileUploading = false;
}
And in your FileUpload.razor component:
#if (fileUploading )
{
<span>- File Uploading...</span>
}
<InputFile OnChange="#UploadSvgFileAsync" />
I recommend reading the following articles to learn how to properly work with files in Blazor apps:
File Uploads
File Downloads
FileInfo file = new FileInfo(yourFile);
get the files byte size:
var fileBytes = file.Length;
turn bytes to MBs:
var fileMBs = fileBytes / (1024*1024);
Related
I am trying to upload large files (regardless of file type) into SQL Server database.
But when I upload a large one (at least 13.2MB or more) it appears the next error message:
System.IO.IOException: Supplied file with size 13897053 bytes exceeds the maximum of 512000 bytes.
When the user uploads the files I call the next method to save the files into IList<IBrowserFile>.
private IList<IBrowserFile> Files = new List<IBrowserFile>();
private int MaxAllowdFiles = int.MaxValue;
private long MaxSizeFiles = long.MaxValue;
private async Task OnInputFileChanged(InputFileChangeEventArgs e)
{
ClearDragClass();
/*var files = e.GetMultipleFiles();
foreach(var file in files)
{
Files.Add(file);
Console.WriteLine(Path.GetFullPath(file.Name));
}*/
//using var content = new MultipartFormDataContent();
foreach (var file in e.GetMultipleFiles(MaxAllowdFiles))
{
using var f = file.OpenReadStream(MaxSizeFiles);
using var fileContent = new StreamContent(f);
fileContent.Headers.ContentType = new MediaTypeHeaderValue(file.ContentType);
Files.Add(file);
}
}
Once the user has uploaded all the files, they click on a button that call the next method to upload it into a database.
private async void Upload()
{
List<string>? notUploadFiles = new();
foreach (var file in Files)
{
using Stream s = file.OpenReadStream();
using MemoryStream ms = new MemoryStream();
await s.CopyToAsync(ms);
byte[] fileBytes = ms.ToArray();
string extn = new FileInfo(file.Name).Extension;
var addArchivoTarea = new AddArchivoTareaRequestDTO(Tarea.Id, file.Name, fileBytes, extn);
var successResponse = await HttpTareas.AddArchivoToTareaAsync(addArchivoTarea);
if (!successResponse)
{
notUploadFiles.Add(file.Name);
}
}
if (notUploadFiles.Count > 0)
{
Snackbar.Configuration.SnackbarVariant = Variant.Filled;
Snackbar.Add("The following files could not be uploaded", Severity.Info);
Snackbar.Configuration.SnackbarVariant = Variant.Outlined;
foreach (var file in notUploadFiles)
{
Snackbar.Add(file, Severity.Error);
}
MudDialog.Close(DialogResult.Ok(true));
}
Snackbar.Add("All files have been successfully uploaded", Severity.Success);
MudDialog.Close(DialogResult.Ok(true));
}
I don't know what I should add or modify to be able to upload large files.
Any suggestions?
According to this
OpenReadStream enforces a maximum size in bytes of its Stream. Reading
one file or multiple files larger than 500 KB results in an exception.
This limit prevents developers from accidentally reading large files
into memory. The maxAllowedSize parameter of OpenReadStream can be
used to specify a larger size if required up to a maximum supported
size of 2 GB.
so you can have:
Stream s = file.OpenReadStream (maxAllowedSize :[the value you prefer]);
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();
}
I'm currently working on a small backup tool written in C# that is supposed to upload files contained within a specified folder to Google Drive via its API. The program largely functions as it's supposed to, the only problem that it is unable to handle files larger than 2GB.
The problem is caused by the upload function itself which is attached down below, it uses a byte array to read the file to subsequently create a Memory Stream. As far as I'm aware (I'm still a beginner when it comes to c#), a byte array can only contain 2GB of information before returning an overflow exception. To combat this I've tried to utilize FileStream.Read (second bit of code attached below) instead of System.IO.File.ReadAllBytes, though this again lead to an overflow exception of the byte Array. I know that at this point I'd have to split the file up, however, due to the rather limited documentation of the GDrive API for C# - at least from what I've seen - and my limited knowledge of C# I've got little to no clue on how to tackle this problem.
I'm sorry for the long read, all help on this matter is highly appreciated.
Upload Function V1 (System.IO.File.ReadAllBytes):
private static Google.Apis.Drive.v3.Data.File UploadFile(Boolean useFolder, String mime, DriveService _service, string _uploadFile, string _parent, string _descrp = "")
{
if (System.IO.File.Exists(_uploadFile))
{
Google.Apis.Drive.v3.Data.File body = new Google.Apis.Drive.v3.Data.File
{
Name = System.IO.Path.GetFileName(_uploadFile),
Description = _descrp,
MimeType = mime
};
if (useFolder)
{
body.Parents = new List<string> { _parent };
}
byte[] byteArray = System.IO.File.ReadAllBytes(_uploadFile);
MemoryStream stream = new System.IO.MemoryStream(byteArray);
try
{
FilesResource.CreateMediaUpload request = _service.Files.Create(body, stream, mime);
request.SupportsTeamDrives = true;
request.Upload();
return request.ResponseBody;
}
catch (Exception e)
{
Console.WriteLine("Error Occured: " + e);
return null;
}
}
else
{
Console.WriteLine("The file does not exist. 404");
return null;
}
}
Upload Method V2 (FileStream):
private static Google.Apis.Drive.v3.Data.File UploadFile(Boolean useFolder, String mime, DriveService _service, string _uploadFile, string _parent, string _descrp = "")
{
if (System.IO.File.Exists(_uploadFile))
{
Google.Apis.Drive.v3.Data.File body = new Google.Apis.Drive.v3.Data.File
{
Name = System.IO.Path.GetFileName(_uploadFile),
Description = _descrp,
MimeType = mime
};
if (useFolder)
{
body.Parents = new List<string> { _parent };
}
//byte[] byteArray = System.IO.File.ReadAllBytes(_uploadFile);
using (FileStream fileStream = new FileStream(_uploadFile, FileMode.Open, FileAccess.Read))
{
Console.WriteLine("ByteArrayStart");
byte[] byteArray = new byte[fileStream.Length];
int bytesToRead = (int)fileStream.Length;
int bytesRead = 0;
while (bytesRead > 0)
{
int n = fileStream.Read(byteArray, bytesRead, bytesToRead);
if (n == 0)
{
break;
}
bytesRead += n;
Console.WriteLine("Bytes Read: " + bytesRead);
bytesToRead -= n;
Console.WriteLine("Bytes to Read: " + bytesToRead);
}
bytesToRead = byteArray.Length;
MemoryStream stream = new System.IO.MemoryStream(byteArray);
try
{
FilesResource.CreateMediaUpload request = _service.Files.Create(body, stream, mime);
request.SupportsTeamDrives = true;
request.Upload();
return request.ResponseBody;
}
catch (Exception e)
{
Console.WriteLine("Error Occured: " + e);
return null;
}
}
}
else
{
Console.WriteLine("The file does not exist. 404");
return null;
}
}
MemoryStream's constructors only work with byte arrays that are limited to Int32.MaxValue bytes. Why not just use your FileStream object directly?
var fileMetadata = new Google.Apis.Drive.v3.Data.File()
{
Name = "flag.jpg"
};
FilesResource.CreateMediaUpload request;
using (var stream = new System.IO.FileStream(#"C:\temp\flag.jpg", System.IO.FileMode.Open))
{
request = service.Files.Create(fileMetadata, stream, "image/jpeg");
request.Fields = "id";
request.Upload();
}
var file = request.ResponseBody;
Really a file that big you should be using resumable upload but im going to have to dig around for some sample code for that.
I have a winforms application that uses Google Drive to manage files. My file upload method is fairly simple:
public static File UploadFile(string sourcefile, string description, string mimeType, int attempt)
{
try
{
string title = Path.GetFileName(sourcefile);
var file = new File {Title = title, Description = description, MimeType = mimeType};
byte[] bytearray = System.IO.File.ReadAllBytes(sourcefile);
var stream = new MemoryStream(bytearray);
FilesResource.InsertMediaUpload request = DriveService.Files.Insert(file, stream, "text/html");
request.Convert = false;
request.Upload();
File result = request.ResponseBody;
return result;
}
catch (Exception e)
{
if(attempt<10)
{
return UploadFile(sourcefile, description, mimeType, attempt + 1);
}
else
{
throw e;
}
}
}
This works, but prior to using Google Drive, I used an FTP solution, which allowed asynchronous upload operations. I would like to include a progress bar when files are uploading, but I can't figure out if there is a way to call InserMediaUpload asynchronously. Do such capabilities exist?
Thank you.
We just announced 1.4.0-beta version earlier today.
1.4.0-beta has a lot of great features including UploadAsync which optionally gets a cancellation token.
Take a look also in our new Media wiki page.
We still don't support an UpdateAsync method, but if you need to update your progress bar you can use the ProgressChanged event. Remember that the default ChunkSize is 10MB, so if you want to get updates after shorter periods, you should change the ChunkSize accordingly.
Be aware, that in the next release of the library, we will also going to support server errors (5xx)
UPDATE (June 2015):
We did add support for UploadAsync more than 2 years ago. Server errors are supported as well using an ExponentialBackoffPolicy.
I know it's late..but Adding a Progress Bar is fairly simple.
Following is a working piece of code for uploading:
public static File uploadFile(DriveService _service, string _uploadFile, string _parent, string _descrp = "Uploaded with .NET!")
{
if (System.IO.File.Exists(_uploadFile))
{
File body = new File();
body.Title = System.IO.Path.GetFileName(_uploadFile);
body.Description = _descrp;
body.MimeType = GetMimeType(_uploadFile);
body.Parents = new List<ParentReference>() { new ParentReference() { Id = _parent } };
byte[] byteArray = System.IO.File.ReadAllBytes(_uploadFile);
System.IO.MemoryStream stream = new System.IO.MemoryStream(byteArray);
try
{
FilesResource.InsertMediaUpload request = _service.Files.Insert(body, stream, GetMimeType(_uploadFile));
request.ProgressChanged += UploadProgessEvent;
request.ChunkSize = FilesResource.InsertMediaUpload.MinimumChunkSize; // Minimum ChunkSize allowed by Google is 256*1024 bytes. ie 256KB.
request.Upload();
return request.ResponseBody;
}
catch(Exception e)
{
MessageBox.Show(e.Message,"Error Occured");
}
}
else
{
MessageBox.Show("The file does not exist.","404");
}
}
And
private void UploadProgessEvent(Google.Apis.Upload.IUploadProgress obj)
{
label1.Text = ((obj.ByteSent*100)/TotalSize).ToString() + "%";
// update your ProgressBar here
}
Whats the best way to zip up files using C#? Ideally I want to be able to seperate files into a single archive.
You can use DotNetZip to archieve this. It´s free to use in any application.
Here´s some sample code:
try
{
// for easy disposal
using (ZipFile zip = new ZipFile())
{
// add this map file into the "images" directory in the zip archive
zip.AddFile("c:\\images\\personal\\7440-N49th.png", "images");
// add the report into a different directory in the archive
zip.AddFile("c:\\Reports\\2008-Regional-Sales-Report.pdf", "files");
zip.AddFile("ReadMe.txt");
zip.Save("MyZipFile.zip");
}
}
catch (System.Exception ex1)
{
System.Console.Error.WriteLine("exception: " + ex1);
}
This is now built into the framework if you have version 4.5+
Otherwise, use Ionic.
Namespace is System.IO.Packaging.ZIPPackage.
See http://visualstudiomagazine.com/articles/2012/05/21/net-framework-gets-zip.aspx for a story.
Have you looked at SharpZipLib?
I believe you can build zip files with classes in the System.IO.Packaging namespace - but every time I've tried to look into it, I've found it rather confusing...
Take a look at this library:
http://www.icsharpcode.net/OpenSource/SharpZipLib/
It is pretty comprehensive, it deals with many formats, is open-source, and you can use in closed-source commercial applications.
It is very simple to use:
byte[] data1 = new byte[...];
byte[] data2 = new byte[...];
/*...*/
var path = #"c:\test.zip";
var zip = new ZipOutputStream(new FileStream(path, FileMode.Create))
{
IsStreamOwner = true
}
zip.PutNextEntry("File1.txt");
zip.Write(data1, 0, data1.Length);
zip.PutNextEntry("File2.txt");
zip.Write(data2, 0, data2.Length);
zip.Close();
zip.Dispose();
There are a few librarys around - the most popular of which are DotNetZip and SharpZipLib.
Hi i created two methods with the ShapLib library (you can download it here http://www.icsharpcode.net/opensource/sharpziplib/) that would like to share, they are very easy to use just pass source and target path (fullpath including folder/file and extension). Hope it help you!
//ALLYOURNAMESPACESHERE
using ...
//SHARPLIB
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
public static class FileUtils
{
/// <summary>
///
/// </summary>
/// <param name="sourcePath"></param>
/// <param name="targetPath"></param>
public static void ZipFile(string sourcePath, string targetPath)
{
string tempZipFilePath = targetPath;
using (FileStream tempFileStream = File.Create(tempZipFilePath, 1024))
{
using (ZipOutputStream zipOutput = new ZipOutputStream(tempFileStream))
{
// Zip with highest compression.
zipOutput.SetLevel(9);
DirectoryInfo directory = new DirectoryInfo(sourcePath);
foreach (System.IO.FileInfo file in directory.GetFiles())
{
// Get local path and create stream to it.
String localFilename = file.FullName;
//ignore directories or folders
//ignore Thumbs.db file since this probably will throw an exception
//another process could be using it. e.g: Explorer.exe windows process
if (!file.Name.Contains("Thumbs") && !Directory.Exists(localFilename))
{
using (FileStream fileStream = new FileStream(localFilename, FileMode.Open, FileAccess.Read, FileShare.Read))
{
// Read full stream to in-memory buffer.
byte[] buffer = new byte[fileStream.Length];
fileStream.Read(buffer, 0, buffer.Length);
// Create a new entry for the current file.
ZipEntry entry = new ZipEntry(file.Name);
entry.DateTime = DateTime.Now;
// set Size and the crc, because the information
// about the size and crc should be stored in the header
// if it is not set it is automatically written in the footer.
// (in this case size == crc == -1 in the header)
// Some ZIP programs have problems with zip files that don't store
// the size and crc in the header.
entry.Size = fileStream.Length;
fileStream.Close();
// Update entry and write to zip stream.
zipOutput.PutNextEntry(entry);
zipOutput.Write(buffer, 0, buffer.Length);
// Get rid of the buffer, because this
// is a huge impact on the memory usage.
buffer = null;
}
}
}
// Finalize the zip output.
zipOutput.Finish();
// Flushes the create and close.
zipOutput.Flush();
zipOutput.Close();
}
}
}
public static void unZipFile(string sourcePath, string targetPath)
{
if (!Directory.Exists(targetPath))
Directory.CreateDirectory(targetPath);
using (ZipInputStream s = new ZipInputStream(File.OpenRead(sourcePath)))
{
ZipEntry theEntry;
while ((theEntry = s.GetNextEntry()) != null)
{
if (theEntry.Name != String.Empty)
{
using (FileStream streamWriter = File.Create(targetPath + "\\" + theEntry.Name))
{
int size = 2048;
byte[] data = new byte[2048];
while (true)
{
size = s.Read(data, 0, data.Length);
if (size > 0)
{
streamWriter.Write(data, 0, size);
}
else
{
break;
}
}
}
}
}
}
}
}