【问题标题】:Uploading and Downloading in Visual Studio vs. Production在 Visual Studio 中上传和下载与生产
【发布时间】:2016-11-13 00:59:54
【问题描述】:

在 Visual Studio 中创建代码时,它从临时目录运行。但是在托管提供商(专门托管 ASP.NET 站点的提供商)中,它将位于不同的目录中(通常是带有 IIS 的应用服务器虚拟文件夹)。我需要将文件上传到 IIS Web 服务器可以找到它们的目录中,所以下面的用例可以工作。

问:如何在 MVC 控制器/视图中定义我的链接,以便它们在开发和生产(上传和下载)中都可以工作?

用例:我的应用需要允许上传文件(仍然不知道要上传到开发盒的哪个位置),然后通过另一个页面上的链接下载相同的文件.

【问题讨论】:

  • 使用Server.MapPath() 创建和获取文件夹/文件的相对或虚拟路径
  • 附注:确保您有足够的预算来支付托管费用,以便以完全信任的方式运行代码...

标签: c# asp.net asp.net-mvc visual-studio


【解决方案1】:

如果您需要更详细的答案,我会给您一些提示,希望这能让您走上正轨。

  1. 定义一个契约,以便您可以抽象任何具体的文件提供程序实现,以便在您以后需要更改底层文件存储时最大限度地减少对代码的影响和修改。例如,如果您在未来的版本中使用 Azure,您可以实现一个 AzureFileProvider 并使用 Blob 存储您的文件。

    public interface IFileProvider
    {
        UploadResult UploadFile(byte[] fileContent, string fileName);
        DownloadResult DownloadFile(int fileId);
    }
    

为基于文件系统的文件提供程序实现您的接口:

public class FileSystemFileProvider : IFileProvider
{
    public FileSystemFileProvider(string absouteBasePath)
    {
        //Check if absoluteBasPath exists and create the directory if it doesn't.
        if (!Directory.Exists(absouteBasePath))
            Directory.CreateDirectory(absouteBasePath);
    }

    public UploadResult UploadFile(byte[] fileContent, string fileName)
    {
        //TODO: Your upload file implementation here
    }

    public DownloadResult DownloadFile(int fileId)
    {
        //TODO Your download file implementation here
    }
}

您可以根据需要调整合同。在此示例中,UploadResult 和 DownloadResult 是用于检索操作结果的简单类。例如,这可能是 DownloadResult 的定义:

public class DownloadResult
{
    public bool Success { get; set; }
    public byte[] FileContent { get; set; }
    public string DownloadName { get; set; }
    public string SizeInBytes { get; set; }
    //... any other useful properties
}
  1. 在您的 StartupAuth.cs 或 Global.asax(您的引导程序代码运行的地方,使用您的具体实现初始化文件提供程序。这种方法在 IoC 容器到位时效果更好。您可以使用 AutoFac、@987654322 @ 或您喜欢的任何其他人,但请帮自己一个忙并使用一个。

    //read the base path from web.config so you may adjust it on production hosting provider without need to make and compile the app
    var fileBasePath = ConfigurationManager.AppSettings["fileBasePath"];
    
    //get the path as an absolute file system path
    var absoluteBasePath = Server.MapPath(fileBasePath);
    
    //Initialize the file provider with the absolute path
    var fileProvider = new FileSystemFileProvider(absoluteBasePath);
    
    //TODO: Configure your IoC to return the fileProvider instance when an IFileProvider is requested.
    
  2. 正如您在第 2 步中看到的,我从 web.config 文件中读取了一个应用程序设置值。这应该出现在配置文件的 appSettings 部分。

    <appSettings>
      <add key="fileBasePath" value="~/FileStorage"/>
    </appSettings>
    
  3. 有了这一切,你可以像这样将你的 fileProvider 注入你的控制器:

    public class UploadController : Controller
    {
        private readonly IFileProvider fileProvider;
    
        public UploadController(IFileProvider fileProvider)
        {
            this.fileProvider = fileProvider;
        }
    

然后您可以在需要时使用您的提供者进行相关操作。

[HttpPost]
public ActionResult Upload(FileUploadModel model)
{
    //Validate
    if (ModelState.IsValid)
    {
        //Use your fileProvider here to upload the file
        var content = new byte[model.PostedFile.ContentLength];
        model.PostedFile.InputStream.Write(content, 0, content.Length);
        var result = fileProvider.UploadFile(content, model.PostedFile.FileName);
        if (result.Success)
        {
            //TODO: Notify the user about operation success

            return RedirectToAction("Index", "Upload");
        }
    }

    //
    return View(model);
}

希望这会有所帮助!

PS:我不知道为什么代码格式化有点疯狂。

【讨论】:

  • 如果在编号列表中,则额外 4 个空格缩进 :)
  • 非常感谢@Stephen。
  • @KarelTamayo 这是一个非常有趣的答案!这需要我时间消化。我只是在寻找保存上传文件的位置,以便 IIS 在生产中找到它们,但我看到了很多我喜欢的答案,我想调查一下!谢谢!!!
猜你喜欢
  • 2021-03-13
  • 2015-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-15
  • 2016-03-05
相关资源
最近更新 更多