向WCF REST服务发送PDF时字节数组反序列化报错求助
问题分析与解决方案
核心问题
你遇到的反序列化错误,根源在于:
- 请求格式不匹配:WCF的
DataContractJsonSerializer对byte[]类型的反序列化,期望接收Base64编码的字符串,而非你当前发送的数字数组。 - 请求体结构错误:你直接将数字数组作为请求体发送,但设置了
Content-Type: application/json,实际发送的内容并非有效的JSON对象,导致WCF无法解析。 - URL构造不符合契约:你的请求URL缺少
UriTemplate中要求的sessionToken路径参数,且未正确传递其他必填参数(如createApplication、option)。 - 同步XHR与异步语法冲突:你使用了
await但XHR是同步模式,这会导致代码逻辑异常。
具体修复步骤
1. 将PDF文件转为Base64字符串
修改文件读取逻辑,直接读取为Base64格式并去掉前缀:
const file = e.target.files[0]; const reader = new FileReader(); reader.onloadend = async (e) => { // 提取纯Base64字符串(去掉"data:application/pdf;base64,"前缀) const pdfBase64 = e.target.result.split(',')[1]; let ret = await dispatch('createTemplate', { name: this.newForm.name, pdfBase64: pdfBase64, save: false, sessionToken: "你的会话令牌", // 替换为实际的sessionToken createApplication: false, // 根据需求设置 option: "" // 根据需求设置 }); await this.$store.dispatch('hideLoadingScreen'); }; reader.onerror = async () => await this.$store.dispatch('hideLoadingScreen'); reader.onabort = async () => await this.$store.dispatch('hideLoadingScreen'); await this.$store.dispatch('showLoadingScreen'); reader.readAsDataURL(file);
2. 修正请求发送逻辑
构造符合要求的URL和JSON请求体,用Promise包装XHR以支持await:
async function createTemplate({ name, pdfBase64, save, sessionToken, createApplication, option }) { // 构造符合UriTemplate的URL,注意编码特殊字符 const encodedName = encodeURIComponent(name); let url = `${getters.getServiceUrl}rest/${sessionToken}/ImportNewTemplate?commit=${save || true}&createApplication=${createApplication}&templateName=${encodedName}&option=${encodeURIComponent(option)}`; return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open("POST", url, true); xhr.setRequestHeader('Content-Type', 'application/json'); // 构造包含Base64字符串的JSON请求体 const requestBody = JSON.stringify({ templateFile: pdfBase64 }); xhr.onload = () => { if (xhr.status >= 200 && xhr.status < 300) { resolve(JSON.parse(xhr.responseText)); } else { reject(new Error(`请求失败:状态码 ${xhr.status},响应:${xhr.responseText}`)); } }; xhr.onerror = () => reject(new Error("网络请求错误")); xhr.send(requestBody); }); }
3. 确认WCF服务配置(可选)
如果服务端未显式配置请求格式,确保WebInvoke属性包含RequestFormat = WebMessageFormat.Json:
[WebInvoke( UriTemplate = "rest/{sessionToken}/ImportNewTemplate?commit={commit}&createApplication={createApplication}&templateName={templateName}&option={option}", Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json )]
关键说明
- WCF的
DataContractJsonSerializer默认将byte[]序列化为Base64字符串,因此反序列化时也必须传入Base64格式的字符串,而非数字数组。 - 所有URL中的参数(如
templateName)必须用encodeURIComponent编码,避免特殊字符导致的路由错误。 - 必须使用异步XHR并通过Promise包装,才能正确配合
await语法使用。
内容的提问来源于stack exchange,提问作者user2097439
相关产品推荐
相关产品推荐

