ASP.NET Core uploads files using IFormFile with a path in the file name - asp.net-core

[HttpPost("FilePost")]
public async Task<IActionResult> FilePost(List<IFormFile> files)
{
long size = files.Sum(f => f.Length);
var filePath = Directory.GetCurrentDirectory() + "/files";
if (!System.IO.Directory.Exists(filePath))
{
Directory.CreateDirectory(filePath);
}
foreach (var item in files)
{
if (item.Length > 0)
{
using (var stream = new FileStream(filePath,FileMode.CreateNew))
{
await item.CopyToAsync(stream);
}
}
}
return Ok(new { count = files.Count, size, filePath });
}
FormFile. FileName = directory + filename,
Uploaded file, file name with path information, how to do?
I just need to get the name of the file.

I just need to get the name of the file.
Use Path.GetFileName() to get the name of the file , and use Path.Combine() to combine the the save path you want with the file name , try the code like below
var filesPath = Directory.GetCurrentDirectory() + "/files";
if (!System.IO.Directory.Exists(filesPath))
{
Directory.CreateDirectory(filesPath);
}
foreach (var item in files)
{
if (item.Length > 0)
{
var fileName = Path.GetFileName(item.FileName);
var filePath = Path.Combine(filesPath, fileName);
using (var stream = new FileStream(filesPath, FileMode.CreateNew))
{
await item.CopyToAsync(stream);
}
}
}

Seem like you want to get the file name base on your file path.
You can get it into way
using System.IO;
Path.GetFileName(filePath);
or extension method
public static string GetFilename(this IFormFile file)
{
return ContentDispositionHeaderValue.Parse(
file.ContentDisposition).FileName.ToString().Trim('"');
}
Please let me know if you need any help

I faced the same issue with different browsers. IE send FileName with full path and Chrome send only the file name. I used Path.GetFileName() to overcome issue.
Other fix is at your front end side. Refer this to solve from it front end side.

Related

how to read excel file in memory (without saving it in disk) and return its content dotnet core

Im working on a webApi using dotnet core that takes the excel file from IFormFile and reads its content.Iam following the article
https://levelup.gitconnected.com/reading-an-excel-file-using-an-asp-net-core-mvc-application-2693545577db which is doing the same thing except that the file here is present on the server and mine will be provided by user.
here is the code:
public IActionResult Test(IFormFile file)
{
List<UserModel> users = new List<UserModel>();
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
using (var stream = System.IO.File.Open(file.FileName, FileMode.Open, FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
while (reader.Read()) //Each row of the file
{
users.Add(new UserModel
{
Name = reader.GetValue(0).ToString(),
Email = reader.GetValue(1).ToString(),
Phone = reader.GetValue(2).ToString()
});
}
}
}
return Ok(users);
}
}
When system.IO tries to open the file, it could not find the path as the path is not present. How it is possible to either get the file path (that would vary based on user selection of file)? are there any other ways to make it possible.
PS: I dont want to upload the file on the server first, then read it.
You're using the file.FileName property, which refers to the file name the browser send. It's good to know, but not a real file on the server yet. You have to use the CopyTo(Stream) Method to access the data:
public IActionResult Test(IFormFile file)
{
List<UserModel> users = new List<UserModel>();
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
using (var stream = new MemoryStream())
{
file.CopyTo(stream);
stream.Position = 0;
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
while (reader.Read()) //Each row of the file
{
users.Add(new UserModel{Name = reader.GetValue(0).ToString(), Email = reader.GetValue(1).ToString(), Phone = reader.GetValue(2).ToString()});
}
}
}
return Ok(users);
}
Reference

Files uploaded but not appearing on server

I use the code stated here to upload files through a webapi http://bartwullems.blogspot.pe/2013/03/web-api-file-upload-set-filename.html. I also made the following api to list all the files I have :
[HttpPost]
[Route("sharepoint/imageBrowser/listFiles")]
[SharePointContextFilter]
public async Task<HttpResponseMessage> Read()
{
string pathImages = HttpContext.Current.Server.MapPath("~/Content/images");
DirectoryInfo d = new DirectoryInfo(pathImages);//Assuming Test is your Folder
FileInfo[] Files = d.GetFiles(); //Getting Text files
List<object> lst = new List<object>();
foreach (FileInfo f in Files)
{
lst.Add(new
{
name = f.Name,
type = "f",
size = f.Length
});
}
return Request.CreateResponse(HttpStatusCode.OK, lst);
}
When calling this api, all the files uploaded are listed. But when I go to azure I dont see any of them (Content.png is a file I manually uploaded to azure)
Why are the files listed if they dont appear on azure.
According to your description, I suggest you could firstly use azure kudu console to locate the right folder in the azure web portal to see the image file.
Open kudu console:
In the kudu click the debug console and locate the site\wwwroot\yourfilefolder
If you find your file is still doesn't upload successfully, I guess there maybe something wrong with your upload codes. I suggest you could try below codes.
Notice: You need add image folder in the wwwort folder.
{
public class UploadingController : ApiController
{
public async Task<HttpResponseMessage> PostFile()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = Environment.GetEnvironmentVariable("HOME").ToString() + "\\site\\wwwroot\\images";
//string root = HttpContext.Current.Server.MapPath("~/images");
var provider = new FilenameMultipartFormDataStreamProvider(root);
try
{
StringBuilder sb = new StringBuilder(); // Holds the response body
// Read the form data and return an async task.
await Request.Content.ReadAsMultipartAsync(provider);
// This illustrates how to get the form data.
foreach (var key in provider.FormData.AllKeys)
{
foreach (var val in provider.FormData.GetValues(key))
{
sb.Append(string.Format("{0}: {1}\n", key, val));
}
}
// This illustrates how to get the file names for uploaded files.
foreach (var file in provider.FileData)
{
FileInfo fileInfo = new FileInfo(file.LocalFileName);
sb.Append(string.Format("Uploaded file: {0} ({1} bytes)\n", fileInfo.Name, fileInfo.Length));
}
return new HttpResponseMessage()
{
Content = new StringContent(sb.ToString())
};
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
}
public class FilenameMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
{
public FilenameMultipartFormDataStreamProvider(string path) : base(path)
{
}
public override string GetLocalFileName(System.Net.Http.Headers.HttpContentHeaders headers)
{
var name = !string.IsNullOrWhiteSpace(headers.ContentDisposition.FileName) ? headers.ContentDisposition.FileName : Guid.NewGuid().ToString();
return name.Replace("\"", string.Empty);
}
}
}
Result:

Upload file, check for same file name

Hi i'am using this utils, to make file upload and delete upload. MVC 4 LINQ to SQL.
I would like to check if file is already uploaded, and if, make a meassage
to try new file.
Can you help me, getting started, to add code for this ?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
namespace CFire2.SupplyConUtils
{
public static class FileUpload
{
public static char DirSeparator =
System.IO.Path.DirectorySeparatorChar;
public static string FilesPath = "Content" +
DirSeparator + "SupplyUpload" + DirSeparator;
public static string UploadFile(HttpPostedFileBase file)
{
// Check if we have a file
if (null == file) return "";
// Make sure the file has content
if (!(file.ContentLength > 0)) return "";
string fileName = file.FileName;
string fileExt = Path.GetExtension(file.FileName);
// Make sure we were able to determine a proper
// extension
if (null == fileExt) return "";
// Check if the directory we are saving to exists
if (!Directory.Exists(FilesPath))
{
// If it doesn't exist, create the directory
Directory.CreateDirectory(FilesPath);
}
//// Set our full path for saving
var path = Path.Combine(HttpContext.Current.Server.MapPath("~/Content/SupplyUpload"), fileName);
// Save our file
file.SaveAs(path);
// Return the filename
return fileName;
}
public static void DeleteFile(string fileName)
{
// Don't do anything if there is no name
if (fileName.Length == 0) return;
// Set our full path for deleting
var path = Path.Combine(HttpContext.Current.Server.MapPath("~/Content/SupplyUpload"), fileName);
// Check if our file exists
if (File.Exists(path))
{
// Delete our file
File.Delete(path);
}
}
}
}
The MSDN docs for HttpPostedFileBase.FileName says
When overridden in a derived class, gets the fully qualified name of
the file on the client.
So probably you need to add this line to correctly execute your check
string fileName = Path.GetFileName(file.FileName);
and then
var path = Path.Combine(HttpContext.Current.Server.MapPath("~/Content/SupplyUpload"),
fileName);
if(File.Exists(path))
return "The file has been already uploaded!
....

ASP.NET WebApi file upload using guid and file extension

I currently am able to save a file being uploaded to a WebAPI controller, but I'd like to be able to save the file as a guid with the correct file name extension so it can be viewed correctly.
Code:
[ValidationFilter]
public HttpResponseMessage UploadFile([FromUri]string AdditionalInformation)
{
var task = this.Request.Content.ReadAsStreamAsync();
task.Wait();
using (var requestStream = task.Result)
{
try
{
// how can I get the file extension of the content and append this to the file path below?
using (var fileStream = File.Create(HttpContext.Current.Server.MapPath("~/" + Guid.NewGuid().ToString())))
{
requestStream.CopyTo(fileStream);
}
}
catch (IOException)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}
HttpResponseMessage response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.Created;
return response;
}
I can't seem to get a handle on the actual filename of the content. I thought headers.ContentDisposition.FileName might be a candidate but that doesn't seem to get populated.
Thanks for the comments above which pointed me in the right direction.
To clarify the final solution, I used a MultipartFormDataStreamProvider which streams the file automatically. The code is in another question I posted to a different problem here:
MultipartFormDataStreamProvider and preserving current HttpContext
My full provider code is listed below. The key to generating the guid file name is to override the GetLocalFileName function and use the headers.ContentDisposition property. The provider handles the streaming of the content to file.
public class MyFormDataStreamProvider : MultipartFormDataStreamProvider
{
public MyFormDataStreamProvider (string path)
: base(path)
{ }
public override Stream GetStream(HttpContent parent, HttpContentHeaders headers)
{
// restrict what images can be selected
var extensions = new[] { "png", "gif", "jpg" };
var filename = headers.ContentDisposition.FileName.Replace("\"", string.Empty);
if (filename.IndexOf('.') < 0)
return Stream.Null;
var extension = filename.Split('.').Last();
return extensions.Any(i => i.Equals(extension, StringComparison.InvariantCultureIgnoreCase))
? base.GetStream(parent, headers)
: Stream.Null;
}
public override string GetLocalFileName(System.Net.Http.Headers.HttpContentHeaders headers)
{
// override the filename which is stored by the provider (by default is bodypart_x)
string oldfileName = headers.ContentDisposition.FileName.Replace("\"", string.Empty);
string newFileName = Guid.NewGuid().ToString() + Path.GetExtension(oldfileName);
return newFileName;
}
}

Store images into a specified location on local system

I am using Play Framework 2.0.4. Here is my code that I have tried :
public static Result save() throws FileNotFoundException {
Form<Tenant> tenantForm = form(Tenant.class).bindFromRequest();
Form<Ten> tenForm = form(Ten.class).bindFromRequest();
Long tenantid = tenForm.get().tenant_id;
Http.MultipartFormData body = request().body().asMultipartFormData();
Http.MultipartFormData.FilePart picture = body.getFile("logo_url");
if (picture != null) {
String fileName = picture.getFilename();
String contentType = picture.getContentType();
File file = picture.getFile();
tenantForm.get().logo_url = file.getPath();
tenantForm.get().save();
return redirect(
routes.Application.index()
);
} else {
flash("error", "Missing file");
return redirect(
routes.Project.ctstenant(0,"name","asc","","",tenantid)
);
}
}
It will stores the image in temp folder. I want it to store in a specified folder. With the example will be appreciated.
Thanks for the help.
You can move your file from TEMP folder to your file storage directory. Below is the example how to move your uploaded file :
// define file storage path
public static final String fileStoragePath = "D:\\filestorage\\";
// handle form submit action
public static Result save() {
// bind request logic
...
if (picture != null) {
String fileName = picture.getFilename();
String contentType = picture.getContentType();
File file = picture.getFile();
// log message to console
Logger.info("Original file name = " + fileName +
" with Content Type " + contentType);
// Rename or move the file to the storage directory
if (file.renameTo(new File(fileStoragePath + fileName))) {
Logger.info("Success moving file to " + file.getAbsolutePath());
} else {
Logger.info("Failed moving file on " + file.getAbsolutePath());
}
// save your file name or using blob (it is your choice)
...
}
}
Note that, path defined on fileStoragePath must be available before to successfully moving or renaming the uploaded file.