我需要为MTOM配置的绑定中的二进制部分设置特定的内容类型(application / pdf)。
配置或代码中是否可以设置内容类型?对于文件部分,它始终为“ Content-Type:应用程序/八位字节流”
配置:
<binding name="FileTransferServicesBinding"
closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00"
messageEncoding="Mtom" transferMode="Buffered"
maxBufferSize="67108864" maxReceivedMessageSize="67108864">
<security mode="Transport" />
</binding>
当前发送到该服务的内容。该文件的多部分标头应为application / pdf,而不是application / octetstream
POST https://somewebservice HTTP/1.1
MIME-Version: 1.0
Authorization: Basic authhash
SOAPAction: ""
Host: webservicehost
Content-Length: 24517
Expect: 100-continue
Accept-Encoding: gzip, deflate
--uuid:b8366a06-3ecc-4bc4-9809-8c87ad459981+id=1
Content-ID: <http://tempuri.org/0>
Content-Transfer-Encoding: 8bit
Content-Type: application/xop+xml;charset=utf-8;type="text/xml"
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Header>[The soapmessageitself]</s:Envelope>
--uuid:b8366a06-3ecc-4bc4-9809-8c87ad459981+id=1
Content-ID: <http://tempuri.org/1/636787311873257476>
Content-Transfer-Encoding: binary
Content-Type: application/octet-stream // This must be application/pdf
%PDF-1.4
%
1 0 obj
<</Type /Catalog/Pages 2 0 R>> ...
答案 0 :(得分:0)
我不得不猜测您正在编码对请求的响应。如果是这样,您只需将内容类型标头添加到外发邮件中:
OperationContext
.Current
.OutgoingMessageHeaders
.Add ("Content-Type", "application/pdf" );
不确定100%,但是您可能需要首先清除所有现有的传出Content-Type标头。我认为您的邮件经过MTOM编码并不重要。从理论上讲这是透明的。
还...只是问...当流式传输的消息占用的内存少得多时,为什么允许64MB缓冲的消息进行传输...并且速度可能会一样快或更快?您可以保证在高负载的服务中获得更好的性能。
更新:
如果您很幸运地使用了Web api类型的绑定(WebHttpBinding)...,您可以轻松地流式传输您的内容,并指定内容类型。它与我在上面的答案中输入的内容没有什么不同,但是正如您回答的那样,那些标头放到错误的位置。
它应该是:
WebOperationContext
.Current
.OutgoingResponse
.ContentType = "application/pdf";
有一篇很棒的文章/示例here,它以与您的目标相一致的方式完全发展了这个想法。
如果要绑定到较旧的肥皂绑定,则可能需要编写一个自定义消息编码器。该技术非常简单(如果很乏味)。基本思想是,您可以控制以适合您需要的方式编写邮件正文。
编码器本身是微不足道的。围绕它的样板将是乏味的部分。定制编码器从抽象MessageEncoder派生。重要的事情是重写ContentType
,MediaType
,MessageVersion
属性以及ReadMessage
和WriteMessage
方法。 ReadMessage
和WriteMessage
方法有多种处理流和缓冲消息的方法。
丑陋的部分是部署编码器必须编写的样板。您已经建立了一个编码器工厂和一个自定义绑定元素。不是很糟糕,但是很吵。在示例代码包here中有几个完整的蜡球示例(包括工厂和绑定元素支持)……可以为您节省一些时间。
答案 1 :(得分:0)
随着时间的推移,我通过手动构建Soap Call解决了这个问题。由于对此问题有很多悬赏,因此我将标记答案相同但使用WCF库作为正确答案的答案。下面的代码示例以“ byteContent.Headers.Add(” Content-Type“,” application / pdf; name = test.pdf“);”开头我需要对WCF做些什么
static HttpClient client;
static object mutex = new object();
static HttpClient Client
{
get
{
if (client == null)
{
lock (mutex)
{
if (client == null)
{
client = new HttpClient();
client.DefaultRequestHeaders.Add("MIME-Version", "1.0");
client.DefaultRequestHeaders.Add("SOAPAction", "\"\"");
client.DefaultRequestHeaders.ConnectionClose = true;
client.DefaultRequestHeaders.ExpectContinue = false;
client.DefaultRequestHeaders.Add("Authorization", "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(Username + ":" + Password)));
}
}
}
return client;
}
}
public static TResponse Send<TResponse>(string endpoint, string payload, byte[] file)
{
string boundary = Guid.NewGuid().ToString("N");
MultipartContent multipart = new MultipartContent("related", boundary);
multipart.Headers.Remove("Content-Type");
multipart.Headers.TryAddWithoutValidation("Content-Type", "multipart/related; boundary=\"" + boundary + "\"");
multipart.Add(new StringContent(payload, Encoding.UTF8, "text/xml"));
ByteArrayContent byteContent = new ByteArrayContent(file);
byteContent.Headers.Remove("Content-Type");
byteContent.Headers.Add("Content-Type", "application/pdf; name=test.pdf");
byteContent.Headers.Add("Content-Transfer-Encoding", "binary");
byteContent.Headers.Add("Content-ID", "<test.pdf>");
byteContent.Headers.Add("Content-Disposition", "attachment; name=\"test.pdf\"; filename=\"test.pdf\"");
multipart.Add(byteContent);
var result = Client.PostAsync(endpoint, multipart).Result;
result.EnsureSuccessStatusCode();
var resultString = result.Content.ReadAsStringAsync().Result;
TResponse resultTyped = XmlHelper.ToObject<TResponse>(resultString);
return resultTyped;
}