利用Message Contract实现WCF上传大文件。
首先要准备一个数据载体类和WCF服务。
[ServiceContract]
public interface IGetDataService
{
[OperationContract]
void UploadFile(FileData file);
}
[MessageContract]
public class FileData
{
[MessageHeader]
public string FilePath { set; get; }
[MessageBodyMember(Order = 1)]
public Stream FileData { set; get; }
}
接着是服务端具体实现方式。
[OperationContract]
public void UploadModelFile(FileUploadMessage physicalFile)
{
try
{
// upload file
Stream sourceStream = physicalFile.FileData;
if (!sourceStream.CanRead)
throw new IOException("The input stream can not be read!");
string uploadFolder = physicalFile.FilePath.Substring(0, physicalFile.FilePath.LastIndexOf("\\"));
if (!Directory.Exists(uploadFolder))
Directory.CreateDirectory(uploadFolder);
using (FileStream fs = new FileStream(physicalFile.FilePath, FileMode.Create, FileAccess.Write, FileShare.None))
{
//read from the input stream in 4K chunks
//and save to output stream
const int bufferLen = 4096;
byte[] buffer = new byte[bufferLen];
int count = 0;
while ((count = sourceStream.Read(buffer, 0, bufferLen)) > 0)
{
fs.Write(buffer, 0, count);
}
fs.Close();
sourceStream.Close();
}
}
catch (Exception ex)
{
LogManager.GetInstance().WriteErrorLog(string.Format("Upload Model File Fail! Message: {0}", ex.Message));
throw ex;
}
}
最后使用WCF的Client类来调用服务就可以了。
代码实现过程中要注意两点:
1. 使用FileUploadMessage类作为输入参数的OperationContract方法的返回值类型(或者输入参数类型)必须是FileUploadMessage类中已使用的类型,比如FileUploadMessage类中的属性有string和stream,UploadModelFile方法的参数类型就只能是string或者stream类型,不然会报错。不过最保险还是返回void,这样就不会错。
2. 也是UploadModelFile方法的参数类型问题,以标记为MessageContractAttribute的参数类型不能和标记成DataContractAttribute的参数混用,不然也会报错。
WCF配置过程中要注意:
1. 在使用WCF服务的Client端的配置文件中,记得设置maxBufferSize的值和maxReceivedMessageSize的值,不然文件一大就报错了,这里的单位是字节。
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_WcfService" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
2. 在编写WCF服务的Server端添加bindings节点<bindings>这个节点貌似是默认没有帮你配置的,要自己手动添加,在system.serviceModel节点里面,然后在下载service的endpoint的basichttpbinding那个节点里加上bindingConfiguration="LargeDataTransferServicesBinding"属性。
<basicHttpBinding>
<binding name="LargeDataTransferServicesBinding" maxReceivedMessageSize="2147483647"
messageEncoding="Text" transferMode="Streamed" sendTimeout="00:10:00" />
</basicHttpBinding>
</bindings>
<service behaviorConfiguration="FileTransferServiceBehavior"
name="FileTransferService">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="LargeDataTransferServicesBinding" contract="FileTransferService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
详细配置可以参考http://www.cnblogs.com/cuihongyu3503319/archive/2010/09/01/1814394.html。