-1

I have done the function to save a file to a Folder in Server, **I am now trying to get the file back from Server by using HTML download, but haven't found the way to get the correct filepath yet.

After stored a file in a Folder in Server, saved filePath in DB by using Entity Framework, I retrieved file from DB with filePath = /VisitReportAttachments/1ea2b64e-545d-4c50-ae7d-eefa7178d310.png. But this filePath doesn't work right.

 <a href="@file.Path" download="@file.name">Click here to download</a>
//file.Path = /VisitReportAttachments/1ea2b64e-545d-4c50-ae7d-eefa7178d310.png

I got an error: Failed - No file

Take a look at create FilePath path in SaveFile code in Controller:

private void SaveFile(HttpPostedFileBase file)
{
    string serverPath = "\\VisitReportAttachments";
      if (file!= null)
        {
        if (!Directory.Exists(serverPath))
        {
            Directory.CreateDirectory(serverPath);
        }
         var fileName = Guid.NewGuid()+ Path.GetExtension(file.FileName);
         var path = Path.Combine("\\", new DirectoryInfo(serverPath).Name, fileName);
         path = relativePath.Replace(@"\", "/"); //this path is stored to DB
          ....
       //As I mentioned: save file to Server is done. I simply post the code that create the filepath in SQL DB while file is storing to Server*
        }
}

FilePath is stored in DB like: /VisitReportAttachments/1ea2b64e-545d-4c50-ae7d-eefa7178d310.png enter image description here

Need help!

vyclarks
  • 854
  • 2
  • 15
  • 39
  • 1
    You need to return the file after it has been saved. Are you using entityframwork to save the file in the database? – IceCode May 15 '19 at 06:36
  • Entity Framework saves things to databases, not folders. Did you save the actual file to the folder as well as writing a path string into the database? And what is stopping you from getting the file path back from the database? Did you associate it with any kind of ID so you can retrieve it? I note that in your code above, all the important code is missing and there's just a comment "TODO". Have you actually written some code for this? If so please show it, thanks – ADyson May 15 '19 at 06:47
  • Ok, I used Entity to save filePath to SQL server, and actually the file is store in a folder. Of course I have an ID to retrieve it, that why I can get the filePath: /VisitReportAttachments/1ea2b64e-545d-4c50-ae7d-eefa7178d310.png from DB. But the problem is, that filePath is not correct to use Wonder how could I get the correct filePath to use download function as a link. @ADyson – vyclarks May 15 '19 at 06:57
  • @vyclarks I have added my answer below. – IceCode May 15 '19 at 07:02
  • Well, is that folder within a directory which is mapped to a virtual directory in IIS? If not then you need to make it so. Either that or you point your ` – ADyson May 15 '19 at 07:50
  • If the folder is already part of your project, then have you tried `VisitReportAttachments/1ea2b64e-545d-4c50-ae7d-eefa7178d310.png` or `~/VisitReportAttachments/1ea2b64e-545d-4c50-ae7d-eefa7178d310.png` maybe? I don't know your folder structure. What the correct URL is all depends where this folder sits relative to your website's root folder. – ADyson May 15 '19 at 07:52

4 Answers4

1

Found out the solution by using Server.MapPath to Map the filePath to the correct Path.

Instead of using downloadable Link in HTML View, I create Download function in Controller:

[HttpPost]
        [Authorize]
        public ActionResult DownloadAttachment()
        {
            return Json(true);
        }

        [HttpGet]
        public ActionResult Download(Guid? attachmentId)
        {
            var visitAttachment = _visitAttachmentService.FindOne(x => x.Id == attachmentId);
            try
            {
                var serverPath = Server.MapPath(visitAttachment.Path);
                byte[] fileBytes = System.IO.File.ReadAllBytes(serverPath);
                return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, visitAttachment.AttachmentName);

            }
            catch
            {
                return File(Encoding.UTF8.GetBytes(""), System.Net.Mime.MediaTypeNames.Application.Octet, visitAttachment.AttachmentName);
            }

        }

Call this method in View:

<a href="" onclick="Download('@file.Id');">@file.AttachmentName</a>

<script>
    function Download(attachmentId) {
            var url = '/Visits/DownloadAttachment';
            $.post(url,
                {
                    //                  FilePath: filePath
                },
                function (data) {
                    var response = JSON.parse(data);
                    window.location = '/Visits/Download?attachmentId=' + attachmentId;
                },
                "json");
        }
    </script>

It works perfectly now.

vyclarks
  • 854
  • 2
  • 15
  • 39
  • Glad you fixed it...but what's the purpose of having an AJAX request here? The request returns nothing useful, and you don't do anything with the response anyway. `@file.AttachmentName` would do the job directly, I would expect. Then that's one less HTTP request to your server, and no extra AJAX code to maintain – ADyson May 15 '19 at 08:40
  • using @file.AttachmentName will Navigate the website to a View name Download, I want to download it at the current page – vyclarks May 15 '19 at 08:44
  • `window.location` will also navigate the website to that URL. It's the exact equivalent of clicking on a link. See https://stackoverflow.com/questions/1667416/window-location-href-vs-clicking-on-an-anchor . And it can't take you to a View called Download because a) you haven't got one, and b) the action method which that URL links to doesn't return a View. Have you actually tried using the a href directly? Do you actually get a different result versus using the JavaScript? As far as I can see, you shouldn't notice any difference. – ADyson May 15 '19 at 08:46
0

Your private string SaveFile(HttpPostedFileBase file) method should return a NewFile model object that reflects the entity in your database. private NewFile SaveFile(HttpPostedFileBase file)

public class NewFile
{
   public int NewFileId { get; set; } 
   public string FileName { get; set; }
   public string FilePath { get; set; }
}

You will need do something similar to the following code when you save the File:

using (var db = new YourDbContext())
{
   var newFile = new NewFile { FileName = fileName, FilePath = path };

   var savedFile = db.Add(newFile);

   db.SaveChanges();

   return savedFile;   // here is the object you can return to the view and access 
                       // its properties
}
IceCode
  • 1,466
  • 13
  • 22
  • thank you but I already got filePath from DB. But it's not a correct filePath to use in this syntax: @file.name. That is what I am asking for. The filePath is /VisitReportAttachments/1ea2b64e-545d-4c50-ae7d-eefa7178d310.png – vyclarks May 15 '19 at 07:07
  • sure, I did, then got @model.Path = /VisitReportAttachments/1ea2b64e-545d-4c50-ae7d-eefa7178d310.png – vyclarks May 15 '19 at 07:08
  • So you are trying to download the png file when you click the link? And it does not find it.. Is the `VisitReportAttachments` a folder inside your solution? – IceCode May 15 '19 at 07:15
0
    private string SaveFile(HttpPostedFileBase file)
    {
        if (file == null)
            return string.Empty;

        string saveFolder = "VisitReportAttachments";

        string fileName = fileName = Guid.NewGuid() + Path.GetExtension(file.FileName);
        string serverFolderPath = AppDomain.CurrentDomain.BaseDirectory + "/" + saveFolder;
        string savePath = serverFolderPath + "/" + fileName;


        if (!Directory.Exists(serverFolderPath))
            Directory.CreateDirectory(serverFolderPath);

        file.SaveAs(savePath);

        return Url.Content($"~/{saveFolder}/{fileName}");
    }
Cem PEHLIVAN
  • 141
  • 3
  • thank you but I already got filePath from DB. But it's not a correct filePath to use in this syntax: @file.name. That is what I am asking for. The filePath is /VisitReportAttachments/1ea2b64e-545d-4c50-ae7d-eefa7178d310.png – vyclarks May 15 '19 at 07:06
-1

You have not shored file in folder. Add below line in code

file.SaveAs(serverPath + file.FileName);

So your C# code will be like

private string SaveFile(HttpPostedFileBase file)
{
    string serverPath = "\\VisitReportAttachments";
      if (file!= null)
        {
        if (!Directory.Exists(serverPath))
        {
            Directory.CreateDirectory(serverPath);
        }
         var fileName = Guid.NewGuid()+ Path.GetExtension(file.FileName);
         var path = Path.Combine("\\", new DirectoryInfo(serverPath).Name, fileName);

         file.SaveAs(serverPath + file.FileName);

         path = relativePath.Replace(@"\", "/");

         return path;
        }
         return string.Empty;
}
manish jadhav
  • 15
  • 2
  • 10
  • please read my question carefully. I used Entity Framwork to save file to Folder, it is quite long so I don't post it in my question. My problem is how to get a correct filepath again to download it – vyclarks May 15 '19 at 06:44
  • Have you saved file to /VisitReportAttachments ? – manish jadhav May 15 '19 at 07:45