When I try to upload an image and save it in a certain folder of the server I get error System.UnauthorizedAccessException in the file.SaveAs(path) line.
View:
Controller:
public ActionResult LoadImage()
{
return View();
}
public ActionResult Upload(HttpPostedFileBase file)
{
//String path = Server.MapPath("~/img/" + file.FileName);
if (file != null)
{
String pic = System.IO.Path.GetFileName(file.FileName);
String path = System.IO.Path.Combine(Server.MapPath("~"), pic);
file.SaveAs(path);
}
return RedirectToAction("index", "Home", null);
An UnauthorizedAccessException means:
The caller does not have the required permission to the folder.
The file is an executable file that is in use.
Path specified a read-only file.
More Info on
Workaround: Using Server Folder instead of full path
Create an Image Folder In solution(or any your choice) as a storage for your images..
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
if (file != null)
{
//Get the file name
var pic = System.IO.Path.GetFileName(file.FileName);
//Get the folder in the server
var imagesDir = System.Web.HttpContext.Current.Server.MapPath("~/image/");
var imgPath = imagesDir + pic;
file.SaveAs((imgPath));
}
return RedirectToAction("index", "Home", null);
}
Cheers,
The possible causes of this exception are:
Permission not granted to the folder where you are uploading the images. (Provide read write permission to the folder if not given)
The folder in which you are uploading is read only.
The file is an executable which may be in use.
Hope this helps.
Related
this is my function to update an instance but here i can't delete the old image it is only delete the instance from the database but the real image doesn't deleted from the image folder i have got this error message
The instance of entity type 'Images' cannot be tracked because another instance with the same key value for {'ImageId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.
public async Task<IActionResult> Edit( int id, [Bind("ImageId,Title,ImageFile")] Images images )
{
if (id != images.ImageId)
{
return NotFound();
}
if (ModelState.IsValid)
{
var im = await _context.Images.FindAsync(id);
//delete image from wwwroot/image
var imagePath = Path.Combine(_hostEnvironment.WebRootPath, "image", im.ImageName);
if (System.IO.File.Exists(imagePath))
System.IO.File.Delete(imagePath);
//save image to wwwroot/image
string wwwRootPath = _hostEnvironment.WebRootPath;
string fileName = Path.GetFileNameWithoutExtension(images.ImageFile.FileName);
string extension = Path.GetExtension(images.ImageFile.FileName);
images.ImageName = fileName = fileName + DateTime.Now.ToString("yymmssfff") + extension;
string path = Path.Combine(wwwRootPath + "/Image", fileName);
using (var fileStream = new FileStream(path, FileMode.Create))
{
await images.ImageFile.CopyToAsync(fileStream);
}
//Edit record
try
{
_context.Update(images);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ImagesExists(images.ImageId))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(images);
}
If you want to get the ImageName only then you should use your find method withAsNoTracking(). Probably you need to change your find method on something like that :
var im = await _context.Images.AsNoTracking().SingleOrDefaultAsync(i => i.Id == id)
About AsNoTracking
It doesn't look like you programmed your action to delete the old image... Deleting the image name from the database doesn't magically delete it from your wwwroot (assuming that's where the image is saved).
You can delete an image programmatically if you have its path like this:
System.IO.File.Delete(path_of_image);
But telling from your code, it doesn't look like you have the path of the image you want to delete. To get the path, I recommend doing either one of these two (if applicable):
Adding another property in your view model for the old image path
Querying the database for the old image path before updating the record
Here is my code for upload a file. It upload the file and save into upload folder. Now want to save the file name in the database. what can i do to save the file name in database.
public ActionResult FileUpload(upload mRegister)
{
//Check server side validation using data annotation
if (ModelState.IsValid)
{
//TO:DO
var fileName = Path.GetFileName(mRegister.file.FileName);
var path = Path.Combine(Server.MapPath("~/Content/Upload"), fileName);
mRegister.file.SaveAs(path);
ViewBag.Message = "File has been uploaded successfully";
ModelState.Clear();
}
return View();
}
Whenever I try to upload a file to a server the current View is redirected to a different View from the controller. How can I upload a file and stay on the same View.
I have tried the following code:
public Action Result(HttpPostedFileBase file)
{
return new EmptyResult();
}
Return View();
Should work as you'd expect, returning the View named Result.
If the current Action Method isn't the view you'd like to return you can use:
return RedirectToAction("actionmethodname");
I would suggest using something like plupload for async upload. That way you can upload without redirect and even view image/document when upload is complete.
It allows multiple upload and fallback through different methods to successfully upload a file.
For implementation you just create another controller just for handling uploads.
Check my code for article submission in MVC architechture.
public ActionResult Submit(ArticleViewModel newSubmit, HttpPostedFileBase uploadFile)
{
if (ModelState.IsValid)
{
//Upload File
if (uploadFile != null)
{
string fileName = uploadFile.FileName;
newSubmit.Article.image = fileName;
uploadFile.SaveAs("~/Content/Uploads/Images");
string savedFileName = Path.Combine(Server.MapPath("~/Content/Uploads/Images"), uploadFile.FileName);
}
// The HTML comes encoded so we decode it before insert into database
newSubmit.Article.content = HttpUtility.HtmlDecode(newSubmit.Article.content);
//Set article flags
newSubmit.Article.flagged = true;
newSubmit.Article.finished = false;
newSubmit.Article.submitStoryFlag = true;
//Insert article in the database _repository.AddArticle(newSubmit);
return View("Submitted");
}
else
{
// Invalid – redisplay with errors
return View(newSubmit);
}
}
Suppose your view name is UploadView.cshtml and from there, you are uploading file.
UploadView.cshtml
#using (Html.BeginForm("UploadFile", "MyController", FormMethod.Post, new { enctype = "multipart/form-data", id = "frm", name = "frm" }))
{
<input id="FileAttachments" type="file" name="FileAttachments" />
<input type="submit" value="upload" />
}
Your Controller would be
MyController.cs
[HttpGet]
public ActionResult UploadView()
{
Return View();
}
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase FileAttachments)
{
if (FileAttachments != null)
{
string fileName = System.Guid.NewGuid().ToString() + Path.GetFileName(FileAttachments.FileName);
fileName = Path.Combine(Server.MapPath("~/Content/Files"), fileName);
FileAttachments.SaveAs(fileName);
}
return View("UploadView");
}
I'm confused about how should I do a model that has some uploaded file, like for exemplo:
User has photos.
I already found out how to upload a file, but the question here is about what to do with the file that was now uploaded, how can I link this new uploaded file(photo in the exemple) with a model(the user in the example).
Thanks.
OBS: Using play for Java here, not Scala.
You have to link your User to his picture. For that, your best option is to use the User id, which should be unique.
Then, if you uploaded your photo under the pictures/user folder in your filesystem, then you should save the picture as pictures/user/USER_ID.png (png or jpg or anything else).
Then, you can have an action which retrieve the picture according to the user id:
public static Result picture(String userId) {
Picture picture = Picture.findPicture(userId);
if (picture != null) {
response().setContentType(picture.contentType);
return ok(picture.bytes);
}
return notFound();
}
And the Picture class looks like:
public class Picture {
public byte[] bytes;
public String contentType;
public static Picture findPicture(String userId) {
String[] extensions = {"png","jpg"}; // an enum should be better
for (String extension:extensions) {
String path = "pictures/user/" + userId + "." + extension;
if (new File().exists(path)) {
Picture picture = new Picture();
picture.bytes = IOUtils.toByteArray(new FileInpustream(path));
picture.contentType = findContentType(extension);
return picture;
}
}
return null;
}
protected static String findContentType(String extension) {
if (extension.equalsIgnoreCase("jpg") {
return "image/jpeg";
} else if (extension.equalsIgnoreCase("png") {
return "image/png";
}
}
}
I did something similar once (but the pictures were stored in memory), you can take a look here.
Just create a convention if user has only one picture. Per instance, if your user was registered in 2012-07-23 and has id = 100, move the file to some place mapped from these data:
/uploaded-dir/2012/07/23/100/picture.jpg
After that, you can use the same convention to read the file.
public ActionResult GetAttachment1(string projectID)
{
return File("~/Uploads/Project", "application/pdf", projectID);
}
this code gives an error......
You need to specify an absolute path to the File method. Use Server.MapPath to convert a relative into an absolute path:
public ActionResult GetAttachment1(string projectID)
{
string projectPath = Server.MapPath("~/Uploads/Project");
string file = Path.Combine(projectPath, projectID);
// at this stage file will look something like this
// "c:\inetpub\wwwroot\Uploads\Project\foo.pdf". Make sure that
// this is a valid PDF file and pass it to the File method
return File(file, "application/pdf", projectID);
}