File Upload/Download Between Blazor And ASP.NET.
Implement file upload/download between Blazor WebAssembly app and ASP.NET app.
Project page: https://github.com/arvinboggs/BlazorUploadDownload
File Upload
Open (or create) a Blazor WebAssembly project. In case you are creating a new Blazor WebAssembly project, make sure the “ASP.NET Core hosted” checkbox is ticked.
- On the client-side (Blazor) project and on the page that the user will use to upload a file, add an
InputFileelement. Please note thatInputFileis not a regular HTML element but is part of theMicrosoft.AspNetCore.Components.Formsnamespace so you have to include that namespace in yourusingsection if you haven’t done so already.1
<InputFile OnChange="OnInputFileChange" />
- Add an HTML element to display error or success message from the server. Note that the content of the
divis bound to the variable namedMessage. This step is optional and is not required to upload a file.1
<div>@Message</div>
- On the code-behind, declare an
HttpClientvariable that will be automatically initialized via dependency injection.1
[Inject] HttpClient mHttpClient { get; set; }
- Declare the variable that will hold the error or success message from the server.
1
string Message;
- On the code-behind, add a function to handle the
OnChangeevent. Whenever the user clicks on theInputFile, the browser will display a dialog box upon which the user may choose a local file to upload. After choosing a file, theOnChangeevent is triggered.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
async Task OnInputFileChange(InputFileChangeEventArgs e) { const long pMaxFileSize = 2000000; // 2 million bytes if (e.File.Size > pMaxFileSize) { Message = "Max allowed upload size is " + pMaxFileSize.ToString("N") + ". You attempted to upload " + e.File.Size.ToString("N") + "."; return; } var pContent = new MultipartFormDataContent(); var pFileContent = new StreamContent(e.File.OpenReadStream(pMaxFileSize)); // Use this MultipartFormDataContent.Add overload. If you use the other overloads, the file might not show up on the server-side method. pContent.Add(pFileContent, "file", e.File.Name); // The following code is optional. Use this line to pass string data to the server together with the uploaded file. pContent.Add(new StringContent(Guid.NewGuid().ToString()), "FileID"); // "Upload" is the base name of your server-side controller. // "UploadFile" is the method inside the controller. var pUrl = "Upload/UploadFile"; var pResult = await mHttpClient.PostAsync(pUrl, pContent); // pResultContent will contain whatever string data was returned by the server-side method. var pResultContent = await pResult.Content.ReadAsStringAsync(); if (pResult.IsSuccessStatusCode) // we will be here if server responds with Ok("my message") Message = "Upload success: " + pResultContent; else // we will be here if server responds with BadRequest("my message") Message = "Upload failed: " + pResultContent; }
- On the server-side project, add a method to receive the file to be uploaded.
1 2 3 4 5
[HttpPost("UploadFile")] public ActionResult UploadFile() { }
- Save the uploaded file into the server’s local disk.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
var pFile = Request.Form.Files.FirstOrDefault(); if (pFile == null) return BadRequest("Please upload at least 1 file."); // optional lines. If you had pass additional data from the client-side, you can get them here. var pFileID = Request.Form["FileID"]; Console.WriteLine("FileID: " + pFileID); var pPath = Path.Combine(Program.AppPath,"temp"); if (!Directory.Exists(pPath)) Directory.CreateDirectory(pPath); pPath = Path.Combine(pPath, pFile.FileName); using (var pStream = new FileStream(pPath, FileMode.Create)) pFile.CopyTo(pStream); // respond with a custom message back to the client-side return Ok("FileID (from browser): " + pFileID);
File Download
- On the client-side project and on the page that the user will use to download a file, add an
buttonelement.1
<button @onclick="OnDownloadFileClick">Download file from server</button>
- On the code-behind, declare an
IJSRuntimevariable that will be automatically initialized via dependency injection.1
[Inject] IJSRuntime mJs { get; set; }
- Add a function to handle the
onclickevent.1 2 3 4 5 6 7 8
async Task OnDownloadFileClick() { // "Download" is the base name of your server-side controller. // "DownloadFile" is the method inside the controller. var pUrl = "api/Download/DownloadFile"; // use JavaScript interop to download the file. await mJs.InvokeVoidAsync("open", pUrl, "_blank"); }
- On the server-side project, add a function that allows the client-side to download a file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
[HttpGet("DownloadFile")] public ActionResult DownloadFile() { var pPath = Path.Combine(Program.AppPath, "temp"); if (!Directory.Exists(pPath)) return BadRequest("No file to download. Upload a file first."); var pDirectory = new DirectoryInfo(pPath); // Get all files inside the <server_path>/temp folder var pFiles = pDirectory.GetFiles(); if (pFiles.Count() == 0) return BadRequest("No file to download. Upload a file first."); // Sort the files from newest to oldest. We will return the newest file. var pSortedFiles = from pFile in pFiles orderby pFile.LastWriteTime descending select pFile; // The 3rd parameter is important. Otherwise, the default filename the user will see is "DownloadFile". return PhysicalFile(pSortedFiles.First().FullName, "application/file", pSortedFiles.First().Name); }
