说明
在HTML中上传文件时会为文件内容加入一头一尾,使用浏览器自带的调试工具可看到请求头中有Request Payload数据如下所示:
-----------------------8cc0b8cfcfd5ed2 Content-Disposition: form-data; name="file"; filename="item3.xml" Content-Type: application/octet-stream 这里是真正的文件内容 -----------------------8cc0b8cfcfd5ed2--
因此服务端接收后要手动对其作解析。
代码
网页端
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf8" /> <meta http-equiv="pragma" content="no-cache" /> <title>测试页</title> </head> <body> 文件上传页 <form action="http://localhost:4513/IVisitorRestService/Upload/utf-8" method="POST" enctype="multipart/form-data"> <input type="file" name="fileContent" /><!--这里的name属性必须有,否则浏览器不会将其作为表单内容进行提交--> <input type="submit" /> </form> </body> </html>
服务端
契约
/// <summary> /// 使用HTML上传文件 /// </summary> /// <param name="file">文件流</param> /// <param name="encodingName">HTML的文字编码名</param> [WebInvoke(Method = "POST", UriTemplate = "Upload/{encodingName}")] void Upload(Stream file, string encodingName);
实现
public void Upload(Stream file, string encodingName) { using (var ms = new MemoryStream()) { file.CopyTo(ms); ms.Position = 0; var encoding = Encoding.GetEncoding(encodingName); var reader = new StreamReader(ms, encoding); var headerLength = 0L; //读取第一行 var firstLine = reader.ReadLine(); //计算偏移(字符串长度+回车换行2个字符) headerLength += encoding.GetBytes(firstLine).LongLength + 2; //读取第二行 var secondLine = reader.ReadLine(); //计算偏移(字符串长度+回车换行2个字符) headerLength += encoding.GetBytes(secondLine).LongLength + 2; //解析文件名 var fileName = new System.Text.RegularExpressions.Regex("filename=\"(?<fn>.*)\"").Match(secondLine).Groups["fn"].Value; //一直读到空行为止 while (true) { //读取一行 var line = reader.ReadLine(); //若到头,则直接返回 if (line == null) break; //若未到头,则计算偏移(字符串长度+回车换行2个字符) headerLength += encoding.GetBytes(line).LongLength + 2; if (line == "") break; } //设置偏移,以开始读取文件内容 ms.Position = headerLength; ////减去末尾的字符串:“\r\n--\r\n” ms.SetLength(ms.Length - encoding.GetBytes(firstLine).LongLength - 3 * 2); using (var fileToupload = new FileStream("D:\\FileUpload\\" + fileName, FileMode.Create)) { ms.CopyTo(fileToupload); fileToupload.Close(); fileToupload.Dispose(); } } }