浏览共享文件夹上的文件并返回客户端选择的完整路径,而不上传文件

时间:2012-01-05 04:36:57

标签: c# javascript ajax browser file-upload

我正在尝试为用户提供基于Web的解决方案,以便在共享驱动器上选择文件。 我想在你去浏览文件时使用windows提供的典型文件选择器。我需要的唯一信息是完整的文件名+路径。现在一个明显的解决方案是只有一个自由文本文本框,用户输入文件名,但我需要使用文件选择器。 (如下图所示)

作为旁注,我正在使用Telerik控件,此下载功能位于父页面中ajaxified面板内的用户控件中。

file selection dialog

目前我有这个标记:

Add a Link to a Document: <input type="file" id="upLink" runat="server" onchange="LinkSelected(this);" />
<asp:HiddenField ID="hdnLinkFile" runat="server" />
<asp:Button ID="btnLink" runat="server" CssClass="invisiblebutton" OnClick="LinkFile" />

<script>
    function LinkSelected(sender) {
        if (sender && sender.value.length > 0) {
            //save filename to hidden value as it will not otherwise be usable on the server without a postback
            $("#<%= hdnLinkFile.ClientID %>").val(sender.value);
            //clear 
            sender.value = null;
            //fire server request on this user control
            $find("<%= RadAjaxManager.GetCurrent(Page).ClientID %>").ajaxRequestWithTarget("<%= btnLink.UniqueID %>", "");
        }
    }
</script>
代码背后的代码:

protected void LinkFile(object sender, EventArgs e)
{
     if (hdnLinkFile.Value.Length > 2 && hdnLinkFile.Value.Substring(0, 2) != @"\\")
     {
         Code.Common.DisplayMessage("File must be in a shared location!", Page);
     }
     else
     {
         //save link string to database
     }
}

此代码的目的是防止完整的回发。完整的回发将导致文件输入(upLink)将所选文件上载到Web服务器。由于我们允许链接到大文件(超过100MB),而我想要的只是文件路径(并且某些客户端的互联网非常慢),因此无需上传。

此代码在IE中运行良好 - 不幸的是,对于type = file的输入,Firefox只返回文件名 - 而不是完整路径+名称。因为Firefox不提供这些数据,因为它被认为是一种安全风险,而且客户端默认使用firefox,我需要找到另一种方式。我想要的只是完整的文件名+路径,而不是实际上传文件 - 它有多难?

1 个答案:

答案 0 :(得分:0)

不幸的是,我发现如何做的唯一方法是构建我自己的文件选择器对话框。看到我已经在使用Telerik控件,我使用了RadTreeView和RadWindow,如下所示。我已经完成了所有验证,以使其更简单。它基于Telerik演示here


Explorer.aspx(弹出窗口)

<script type="text/javascript">
   function onNodeClicking(sender, args) {
      //fill path textbox
      var textbox = document.getElementById('inpPath');
      if (args.get_node()._parent._uniqueId == "RadTreeView1")
         textbox.value = args.get_node()._properties._data.value; //root node
      else
         textbox.value = args.get_node()._parent._properties._data.value + "\\" + args.get_node()._getData().text;
   }

   function onCancel() {
      var wnd = getRadWindow();
      var openerPage = wnd.BrowserWindow;
      openerPage.OnFileSelected('');
      wnd.close();
   }

   function onOK() {
      var wnd = getRadWindow();
      var openerPage = wnd.BrowserWindow;
      openerPage.OnFileSelected(document.getElementById('inpPath').value);
      wnd.close();
   }

   function getRadWindow() {
        var oWindow = null;
        if (window.radWindow) oWindow = window.radWindow;
        else if (window.frameElement.radWindow) oWindow = window.frameElement.radWindow;
        return oWindow;
   }
</script>

<div id="divFolderPath" style="padding: 0px 0px 10px 10px;">
   <input id="inpPath" runat="server" type="text" style="width:80%;" />&nbsp;&nbsp;
   <asp:Button ID="btnGo" runat="server" Text="Go" onclick="btnGo_Click" />
</div>

<div id="divButtons" style="padding: 0px 0px 15px 10px; text-align:center;">
   <input id="btnOk" type="button" value="OK" onclick="onOK()" style="padding-right:5px;" disabled="disabled" />
   <input id="btnCancel" type="button" value="Cancel" onclick="onCancel()" />
</div>

<telerik:RadTreeView ID="RadTreeView1" runat="server"
   OnNodeExpand="RadTreeView1_NodeExpand"
   OnClientNodeClicking="onNodeClicking">
</telerik:RadTreeView>



代码背后:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web.UI;
using System.IO;
using Telerik.Web.UI;

//extensions we have pics for
private readonly string[] _knownExtensions = new[] { "csv", "doc", "docx", "gif", "html", "jpg", "pdf", "png", "txt", "xls", "xlsx", "xml" }; 

protected void Page_Load(object sender, EventArgs e)
{
   if (!Page.IsPostBack)
   {
      if (Session["nodes"] != null && ((List<string>)Session["nodes"]).Count > 0)
      {
         foreach (string nod in (List<string>)Session["nodes"])
         {
            AddNode(nod);
         }
      }
      else
      {
         AddNode(ConfigurationManager.AppSettings["LinkDocumentStartPath"]);
      }
   }
}

private void AddNode(string rootpath)
{
   Directory.GetDirectories(rootpath);
   inpPath.Value = rootpath;
   //won't get this far if it fails the first check
   var dirNode = new RadTreeNode(rootpath)
   {
      Value = rootpath,
      ImageUrl = "~/Content/Images/folder.png",
      Expanded = true,
      ExpandMode = TreeNodeExpandMode.ServerSideCallBack
   };
   dirNode.Attributes.Add("isFile", "false");
   RadTreeView1.Nodes.Add(dirNode);
}

protected void RadTreeView1_NodeExpand(object sender, RadTreeNodeEventArgs e)
{
   BindTreeToDirectory(e.Node.Value, e.Node);
}

private void BindTreeToDirectory(string path, RadTreeNode parentNode)
{
   //get directories
   string[] directories = Directory.GetDirectories(path);
   foreach (string directory in directories)
   {
      var dirNode = new RadTreeNode(Path.GetFileName(directory))
      {
         Value = path + "/" + Path.GetFileName(directory),
         ImageUrl = "~/Content/Images/folder.png",
         ExpandMode = TreeNodeExpandMode.ServerSideCallBack
      };
      dirNode.Attributes.Add("isFile","false");
      parentNode.Nodes.Add(dirNode);
   }
   //get files in directory
   string[] files = Directory.GetFiles(path);
   foreach (string file in files)
   {
      var node = new RadTreeNode(Path.GetFileName(file));
      node.Attributes.Add("isFile", "true");
      //get extension
      string extension = Path.GetExtension(file);
      if (!string.IsNullOrEmpty(extension))
      {
         extension = extension.ToLower().TrimStart('.');
      }
      //choose an image for the extension
      if (Array.IndexOf(_knownExtensions, extension) > -1)
      {
         node.ImageUrl = "~/Content/Images/" + extension + ".png";
      }
      else
      {
         node.ImageUrl = "~/Content/Images/unknown.png";
      }
      parentNode.Nodes.Add(node);
   }
}

//go to a new directory
protected void btnGo_Click(object sender, EventArgs e)
{
   string nod = inpPath.Value.Trim();
   if (!string.isNullOrEmpty(nod))
   {
      var nodeslst = new List<string>();
      if (Session["nodes"] != null)
      {
         nodeslst = (List<string>) Session["nodes"];
      }
      else
      {
         //session has expired - get nodes from radtree
         nodeslst.AddRange(from RadTreeNode rtn in RadTreeView1.Nodes select rtn.Value);
      }
      if (nodeslst.Contains(nod, StringComparer.OrdinalIgnoreCase) == false)
      {
         AddNode(nod);
         nodeslst.Add(nod);
      }
      Session["nodes"] = nodeslst;
   }
}



,此代码位于包含文件选择按钮的页面上:

<span style="width:200px; display:inline-block; text-align:right; padding-right:5px;">Add a Link to a Document:</span>
<telerik:RadTextBox ID="txtLinkFileName" runat="server" Width="325px" Enabled="False"></telerik:RadTextBox>
<asp:Button ID="selectFile" OnClientClick="OpenFileExplorerDialog(); return false;" Text="Browse..." runat="server" />

<asp:Button ID="btnLink" runat="server" CssClass="invisiblebutton" OnClick="LinkFile" CausesValidation="false" />

<telerik:RadWindow runat="server" Width="550px" Height="560px" VisibleStatusbar="false"
   ShowContentDuringLoad="false" NavigateUrl="Explorer.aspx" ID="ExplorerWindow"
   Modal="true" Behaviors="Close,Move,Resize">
</telerik:RadWindow>

<script type="text/javascript">
    function OpenFileExplorerDialog() {
        var wnd = $find("<%= ExplorerWindow.ClientID %>");
        wnd.show();
    }

    //This function is called from code on the Explorer.aspx page
    function OnFileSelected(fileSelected) {
        if (fileSelected && fileSelected.length > 0) {
            var textbox = $find("<%= txtLinkFileName.ClientID %>");
            textbox.set_value(fileSelected);
            $find("<%= RadAjaxManager.GetCurrent(Page).ClientID %>").ajaxRequestWithTarget("<%= btnLink.UniqueID %>", "");   
        }
    }
</script>



代码背后:

protected void LinkFile(object sender, EventArgs e)
{
   if (!string.IsNullOrEmpty(txtLinkFileName.Text))
   {
      if (txtLinkFileName.Text.Length > 2 && txtLinkFileName.Text.Substring(0, 2) != @"\\")
      {
         Code.Common.DisplayMessage("File must be in a shared location!", Page);
      }
      else
      {
         //just a link to a file - no need to upload anything
         //save filepath to database
         //filepath = txtLinkFileName.Text;
      }
   }
}

正如你所看到的,如果smartypants浏览器不是试图保护我们自己,但仍然可以实现,那将会容易得多。