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);
}
Related
I am using .Net Core 5 and uploading images for my Trademark. I use Repository for my work and got error CS706: There is no argument given that corresponds to the required formal parameter 'photo' of 'Interface.Create(Trademark, IFormFile)' in Controller
_trademarkRepo.CreateNewTrademark(trademark);
Controller
public IActionResult CreateTrademark(Trademark trademark)
{
if(ModelState.IsValid)
{
_trademarkRepo.CreateNewTrademark(trademark);
}
_logger.LogInformation("...");
return RedirectToAction("Index");
}
Repo
public bool CreateNewTrademark(Trademark trademark, IFormFile photo)
{
var path = Path.Combine(this._webHostEnvironment.WebRootPath, "trademarks", photo.FileName);
var stream = new FileStream(path, FileMode.Create);
photo.CopyToAsync(stream);
if(CheckExist(trademark.TrademarkName))
{
return false;
}
var newTrademark = new Trademark
{
TrademarkName = trademark.TrademarkName,
Description = trademark.Description,
Image = photo.FileName
};
_dbContext.Trademarks.Add(newTrademark);
_dbContext.SaveChanges();
return true;
}
From error it is evident that what error is.
Method at repo level required two argument. One is trademark and another is photo.
When you have called that from controller , you have only passed one. (Trademark only and photo is missing). This is the error.
Basically your controller should look like following.
public IActionResult CreateTrademark(Trademark trademark,IFromFile photo)
{
if(ModelState.IsValid)
{
_trademarkRepo.CreateNewTrademark(trademark,photo);
}
_logger.LogInformation("...");
return RedirectToAction("Index");
}
Note: There are many other dependencies like how you post file from UI etc. That is not scope of this question and so answer. You have to look for those detail.
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.
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.
I have a Action in controller as
public ActionResult Download()
{
return File(FileStream, "application/octet-stream", fileName);
}
If I want to use FilePathresult as:
public FilePathResult Download()
{
return File(FileStream, "application/octet-stream", fileName);
}
can I call the Download() on click of a button like this
#Html.ActionLink("FileDownload", "Download", new { file = item.FileName, GuID = item.DocumentGuID }) /text).Width(10);
Also is the implementation of Download() is correct in the second instance i.e.,in
public FilePathResult Download()
?
Your ActionLink defines parameters that you want to pass so you will need to add those to your action
#Html.ActionLink("FileDownload", "Download", new { file = item.FileName, GuID = item.DocumentGuID }) /text).Width(10);
I'm not sure what /text.Width(10); is doing there but a properly formed ActionLink with parameters also must define the Html Attributes as the last parameter, just pass in null.
Here is an example of a properly formed ActionLink.
#Html.ActionLink("ActionName", "ControllerName", new { id = 10}, null)
You have a file and a GuID parameter in your link, so add those to your action as parameters.
public FilePathResult Download(string file, Guid GuID)
{
return File(FileStream, "application/octet-stream", fileName);
}
Give it a try and let us know what happens :-)
Happy coding!
I have a controller action method that needs to be able to serve multiple views. These views are generated by XSLT.
Now, the views have images in them (hundreds each), and each view needs to have its own folder with images to refer to. How should this work?
If the images in the source XML has an href that is a simple relative path ("images/image.svg"), how can I get this path to resolve in the view in the application?
If I could put the images folder in the same folder as the view, and use a relative path there, it would be easy, but that doesn't work, because I'm serving multiple views from the action. Here is the routing:
routes.MapRoute(
"Parameter",
"{controller}/{action}/{lang}/{prod}",
new { controller = "Manuals", action = "Product", lang = "en-US", prod = "sample" }
);
So if I try using a relative path for the img src attribute, it resolves to something like "/Manuals/Product/en-US/images/image.svg"
And in fact, if I put it relative to the view, the image is located in "/Views/Manuals/en-US/images/image.svg"
So is there no way to have relative image paths like this in Asp.Net MVC? Or am I misunderstanding MVC routing completely?
This is what I have done before:
public class MvcApplication : HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
MapRoute(routes, "", "Home", "Index");
/* other routes */
MapRoute(routes, "{*url}", "Documentation", "Render");
}
}
Now any routes that are not matched are passed to the DocumentationController. My documentation controller looks as follows:
public class DocumentationController : Controller
{
public ActionResult Render(string url)
{
var md = new MarkdownSharp.Markdown();
// The path is relative to the root of the application, but it can be anything
// stored on a different drive.
string path = Path.Combine(Request.MapPath("~/"), GetAppRelativePath().Replace('/', '\\')) + ".md";
if (System.IO.File.Exists(path))
{
string html = md.Transform(System.IO.File.ReadAllText(path));
return View("Render", (object)html);
}
// return the not found view if the file doesn't exist
return View("NotFound");
}
private string GetAppRelativePath()
{
return HttpContext.Request.AppRelativeCurrentExecutionFilePath.Replace("~/", "");
}
}
All this does is to find markdown files and render them accordingly. To update this for your case, you may want to do the following:
routes.MapRoute(
"Parameter1",
"{controller}/{action}/{lang}/{*url}",
new { controller = "Manuals", action = "Download", lang = "en-US", prod = "sample" }
);
Make sure it is after the {controller}/{action}/{lang}/{prod} route. This should cause a URL such as /Manuals/Product/en-US/images/image.svg or even images/image.svg (if the browser is in /Manuals/Product/en-US/sample to invoke the the Download action. You can then adapt the code I wrote to map that URI to the physical location. A problem you may run into is that "images" are considered to be product and that /Manuals/Product/en-US/images would think its a product.
The Images action can be can look as follows.
public ActionResult Download(string url)
{
/* figure out physical path */
var filename = /* get filename form url */
var fileStream = [...];
Response.Headers.Remove("Content-Disposition");
Response.Headers.Add("Content-Disposition", "inline; filename=" + filename);
string contentType = "image/jpg";
return File(fileStream, contentType, filename);
}
You can get more information of the FileResult at MSDN.