Is it possible to upload the entire folder with same folder structure using .netcore webapi. I know we can zip and upload, then unzip, just wondering for alternative way to upload as it is instead of zipping
Currently i have updated the controller as below, this logic doesnot consider folders for upload
private async Task<bool> Import()
{
bool isSaveSuccess = false;
string fileName;
var files = Request.Form.Files;
foreach (var file in files)
{
try
{
var extn = "." file.FileName.Split('.')[file.FileName.Split('.').Length - 1];
fileName = file.FileName DateTime.Now.Ticks extn;
//fileName = Path.Combine(file.FileName, DateTime.Now.Ticks extn);
var pathBuilt = Path.Combine(Directory.GetCurrentDirectory(), "Upload\\files1");
if (!Directory.Exists(pathBuilt))
{
Directory.CreateDirectory(pathBuilt);
}
var path = Path.Combine(Directory.GetCurrentDirectory(), "Upload\\files1", fileName);
using (var stream = new FileStream(path, FileMode.Create))
{
await file.CopyToAsync(stream);
}
isSaveSuccess = true;
}
catch
{
_logger.LogError("Request failed: " "err");
}
}
return isSaveSuccess;
}
CodePudding user response:
Yes, it should be possible. Have a look at webkitdirectory
property: https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/webkitdirectory
This will let you select one or more folders, so you can iterate over the inner contents of the users selection. As you can see, this is a "native" feature and not limited to asp.net or c# in any way.
<input type="file" id="files" name="files" webkitdirectory multiple />
<ul id="listing"></ul>
document.getElementById("filepicker").addEventListener("change", function(event) {
let output = document.getElementById("listing");
let files = event.target.files;
for (let i=0; i<files.length; i ) {
let item = document.createElement("li");
item.innerHTML = files[i].webkitRelativePath;
output.appendChild(item);
};
}, false);
As you can see from the demo code, you can get the relative path by calling .webkitRelativePath
, so yit should be no problem to recreate the folder structure on your target.
Be aware, that this feature is not natively available on Internet Explorer and Firefox versions on android below 50.
Update for saving files with subfolders
Here is a bare minimum example of uploading taking any number of uploaded form files and saving them to disk, while keeping the relative folder structure.
First change your controllers constructor to get a your current environment in:
private readonly IWebHostEnvironment _env;
public HomeController(IWebHostEnvironment environment)
{
_env = environment;
}
Then amend your upload logic accordingly:
[HttpPost]
public async Task<IActionResult> Upload([FromForm] IFormFileCollection files)
{
//target in wwwroot for static files
string targetFolder = Path.Combine(_env.WebRootPath, "uploads");
foreach (IFormFile file in files)
{
if (file.Length <= 0) continue;
//fileName is the the fileName including the relative path
string path = Path.Combine(targetFolder, file.FileName);
//check if folder exists, create if not
var fi = new FileInfo(path);
fi.Directory?.Create();
//copy to target
using var fileStream = new FileStream(path, FileMode.Create);
await file.CopyToAsync(fileStream);
}
return View("Index");
}
This will result to your folder and all its subfolders being saved into your wwwroot/uploads/
folder inside your application:
wwwroot/
|
|-uploads
|-MyFolder
|- File1.jpg
|- File2.jpg
|- MyFolder2
|- File3.jpg
I'd recommend saving them somewhere different though, because redeploying might clean out the application folder first, depending on your deployment strategy (xcopy, github actions, azure pipelines, containers ...)