用WebClient将客户端上传文件保存到远端文件服务器

来源:互联网 发布:linux在目录下创建文件 编辑:程序博客网 时间:2024/05/17 23:50

要上传文件到服务器也很简单,可以直接使用Form提交一个enctype = 'multipart/form-data'的表单,再从服务器接收一下就可以了。但如果想将文件传到另一台文件服务器又可以怎样呢。可以从服务器触发一些计划任务,将文件复制过去,也可以使用如BT的方式,同步到多个服务器。其实我还是更喜欢使用后者,这样工作量少很多,特别要同步到多个服务器做负载均衡时。


不过今天要介绍不是上述的方式,是使用WebClient将文件直接PUT到一部文件服务器。直接上代码(.net3.5):

        private void SaveToWebServer(HttpPostedFile hpf)        {            WebClient webClient = new WebClient();            ICredentials c = new NetworkCredential("computer\\user","123123");            try            {                webClient.Credentials = c;                byte[] tmpBytes = new byte[hpf.InputStream.Length];                hpf.InputStream.Read(tmpBytes, 0, tmpBytes.Length);                string fileNameOnly =  GetFileName(hpf.FileName);                webClient.UploadData(new Uri("http://192.168.1.111:90/UploadFiles/" + fileNameOnly), "PUT", tmpBytes);            }            catch (Exception)            {                                throw;            }        }


        private void SaveToWebServer(System.IO.Stream stream)        {            WebClient webClient = new WebClient();            ICredentials c = new NetworkCredential("computer\\user", "123123");            try            {                webClient.Credentials = c;                byte[] tmpBytes = new byte[stream.Length];                stream.Read(tmpBytes, 0, tmpBytes.Length);                string fileNameOnly = GetFileName(Request["up1"]);                webClient.UploadData(new Uri("http://192.168.1.111:90/UploadFiles/" + fileNameOnly), "PUT", tmpBytes);            }            catch (Exception ex)            {                throw;            }        }


上面代码就是创建一个WebClient,设置验证授权,从HttpPostedFile读出上传文件的字节,然后使用WebClient.UploadData( Uri, "Method", byte[] ) 上传到服务器。

Uri中要给定具体的目标路径和文件名。

注意:此时由于文件服务器没相应的处理程序,因此,IIS的网站要打开写权限,和添加相应的用户名。


路径只能是服务器上的虚拟路径,不是目标机器的物理路径。因为访问方式是 http:/www.domain.com/upload/file1.txt  这样的URL。WebClient中还有很多其它上传的方法,如 UploadFile,OpenWrite两个方法可用于上传文件。

UploadFile 是将本地文件上传到服务器,但先要将文件保存到网站所在的Web服务器,再传到目标的文件服务器。

OpenWrite 是打开一个Stream,可将接将浏览器传过来的文件输入流传到目标文件服务器上。

.net 3.5的参考: http://technet.microsoft.com/zh-cn/library/system.net.webclient(v=vs.90).aspx

4.0的内容也一样,但增加一些支持异步和TaskAsync的方法。

既然服务器代码有了,文件服务器的设置也有了,那如何从客户端Post一个文件呢。下面介绍几种方法( WebForm,Form,Ajax)。

表单(不解释):

<body>    <form id="form1" runat="server">    <div>        普通Upload【WebForm】<br />        <asp:FileUpload ID="file1" runat="server" style="width:300px;" />        <br />        <asp:Button ID="btnSubmit1" runat="server" Text = " 保 存 文 件 " />    </div>    </form>    <div>     普通Http Form Tag Upload    <form id="form2" name="form2" action="upload/UploadFileHandler.ashx" method="post" enctype="multipart/form-data">        <input type="file" name="up1" id="up1" style="width:300px;" />        <br />        <input type="submit" id="submit1" name="submit" value=" 保 存 文 件 " />    </form>    </div>    <div>    AjaxForm upload    <form id="form3" name = "form3" action="upload/UploadFileHandler.ashx" method="post" enctype="multipart/form-data">        <input type="file" id="Up2" name="Up2" style="width:300px;" />        <br/>        <input type="button" name="btnUpload" id="btnUpload" value = " 保 存 文 件 " onclick="uploadFileToServer()"/>        <iframe src="about:blank;" id="ajaxFrame" style="width:0px;height:0px;left:-1000px;position:absolute;" name="ajaxFrame"></iframe>    </form>    </div></body>

浏览器上看:


AJAX使用的脚本:

        function uploadFileToServer() {            var xhr = new XMLHttpRequest();            var f3 = document.getElementById("form3");            if (typeof FormData != "undefined") {                var fd = new FormData(f3);                                xhr.open("POST", form3.action, true);                xhr.onreadystatechange = function() {                    if (xhr.status == "200" && xhr.readyState == "4") {                        var d = xhr.responseText;                        var jsonD = eval("(" + d + ")");                        if (jsonD.success) {                            alert("Upload OK");                        }                    }                };                xhr.send(fd);            }            else {                f3.target = "ajaxFrame";                var ajaxF = document.getElementById("ajaxFrame");                ajaxF.setAttribute("onload", "showmsg()");                f3.submit();                            }        }        function showmsg() {            var f = document.getElementById("ajaxFrame");                        var d = "";            if (f.contentDocument) {                d = f.contentDocument.body.innerHTML;            } else {                d = f.contentWindow.document.body.innerHTML;            }            var j = d!=""?eval("(" + d + ")"):new Object();            if (j != undefined) {                if (j["success"] != undefined && j.success) {                    alert("Upload OK");                                    }            }            f.setAttribute("onload", "");            f.src = "about:blank;";        }

脚本中的FormData 是XMLHttpRequest Level2 中使用的,IE9+,Chrome,Opera10+,其它未测试过。

var f = new FormData(form); 就是用Form表单来构造一个FormData对象,xhr.send() 时将整个FormData对象作为参数,传给服务器。


Web服务器接收上传数据(敷衍General HttpHandler .ashx)

如果是WebForm,则使用:

HttpFileCollection hfc = Request.Files;

获取上传的文件列表即可。

如果用的是普通 的Form,即 <form action = ""  method ="" enctype="multipart/form-data"> 这样提交的,使用 

Request.InputStream;
来获取上传流,可以自己分割多个文件。如果预知页面的file控件的name属性,也可以Request到。

Request["file1"];

最后就使用开头的方法,将流使用WebClient发送到远端的文件服务器。如果需要同步到其它分流服务器,就各显神通吧。


如果有域名及负载均衡的环境,就有需要将文件放到一个独立的静态资源服务器中进行共享,不可以将文件单独存放在网页服务器的本地。


附上Web服务器,文件服务器和客户端关系:


原创粉丝点击