在上传文件的时候,往往需要传递当前用户的一些其它的辅助信息,在此提供一个将这些辅助信息合并入二进制文件中一起上传的方法。
下面代码将选中文件上传的同时,将传送会话Id、文件后缀、文件类型三个参数。
整个合并后的二进制流分成三部分,如下图。第一段用1个字节表示辅助信息的长度,当然,若第二段比较长,则可以用双字节来表示;第二段是辅助信息,这里用json格式的字符串转换成ASCII码数组来表示;第三段为选中文件的实际内容。
页面及JavaScript代码如下:
<input id="File" type="file"/>
// 使用POST方式提交服务器 function SendFileToServer(filename, filecontent) { $.ajax({ type: "POST", url: "PictureService.svc/SendIdCardPicture", dataType: 'application/json; charset=utf-8', cache: false, processData: false, data: filecontent, success: function (data) { console.log(data); } }); } // File控件选择一个文件时触发change后的函数 $('#File').change(function (evt) { // 界面中有type=file的input控件 if (evt.target.files.length > 0) { // 遍历所有type=file的input控件 for (var i = 0; i < this.files.length; i++) { var file = this.files[i]; var reader = new window.FileReader(); // 定义执行下面reader.readAsArrayBuffer后触发的load事件的处理函数 reader.onload = function (rResult) { // 生成文件名 var filename = GetGUID(); // 设置一起传递的辅助信息,这里包含sessionId、 imageType、fileExtName三项数据 var obj = {}; obj.sessionId = $("#sessionId").val(); obj.imageType = 1; obj.fileExtName = "png"; var jsonShop = $.toJSON(obj); // 把字符串转换成由字符ASCII码组成的数组 var arr = Array.prototype.map.call(jsonShop, function (c) { return c.charCodeAt(0); }); // 在上述数组前面加入1个字符长度的数据,用以表示数组长度 arr.unshift(arr.length); // 创建一个全新的ArrayBuffer,长度为上述数组长度+文件长度 var buffer = new ArrayBuffer(rResult.target.result.byteLength + arr.length); // 生成视图,因为只有在视图里才能读取和插入数据 var dataview = new DataView(buffer); // 把数组推入视图 for (var i = 0; i < arr.length; i++) { dataview.setUint8(i, arr[i]); } // 因为rResult.target.result是ArrayBuffer类型,所以需要先转成视图才能读取里面的数据 var result = new DataView(rResult.target.result); // 把文件每个字节推入视图 for (var i = 0; i < rResult.target.result.byteLength ; i++) { dataview.setUint8(i + arr.length, result.getUint8(i)); } // 调用上传方法 SendFileToServer(filename, buffer); }; // 读取文件,该方法会触发load事件,并将生成的ArrayBuffer赋予reader.result。 reader.readAsArrayBuffer(file); }; } });
服务器端代码如下:
[ServiceContract] public class PictureService { [OperationContract] [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)] public bool SendPicture(Stream imageContext) { // 读取二进制数据 byte[] m_Bytes = ReadToEnd(imageContext); // 获取第二段的长度 int len = (int)m_Bytes[0]; // 从二进制数据中复制出第二段数据 byte[] data = new byte[len]; Array.Copy(m_Bytes, 1, data, 0, len); // 将复制出的数据转换成字符串,然后通过jsonConvert反序列化为ImgInfo对象 string Jsonstr = System.Text.Encoding.Default.GetString(data); ImgInfo imgInfo = JsonConvert.DeserializeObject<ImgInfo>(Jsonstr); // 读取图片文件数据 byte[] Imagedata = new byte[m_Bytes.Length - 1 - len]; Array.Copy(m_Bytes, 1 + len, Imagedata, 0, m_Bytes.Length - 1 - len); // 判断保存目录是否存在,若不存在则创建 string filePath = @"D:\Image\"; if (!System.IO.Directory.Exists(filePath)) { System.IO.Directory.CreateDirectory(filePath); } // 生成文件名称 string imageName = DateTime.Now.ToString("yyyyMMDDhhmmss.") + imgInfo.FileExtName; string imageFullPath = filePath + imageName; // 若文件已存在,则放弃 if (!File.Exists(imageFullPath)) { try { // 将获取的二进制数据写入文件 System.IO.File.WriteAllBytes(imageFullPath, Imagedata); imageContext.Close(); return true; } catch { return false; } } else { return false; } } public byte[] ReadToEnd(System.IO.Stream stream) { long originalPosition = 0; if (stream.CanSeek) { originalPosition = stream.Position; stream.Position = 0; } try { byte[] readBuffer = new byte[4096]; int totalBytesRead = 0; int bytesRead; while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0) { totalBytesRead += bytesRead; if (totalBytesRead == readBuffer.Length) { int nextByte = stream.ReadByte(); if (nextByte != -1) { byte[] temp = new byte[readBuffer.Length * 2]; Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length); Buffer.SetByte(temp, totalBytesRead, (byte)nextByte); readBuffer = temp; totalBytesRead++; } } } byte[] buffer = readBuffer; if (readBuffer.Length != totalBytesRead) { buffer = new byte[totalBytesRead]; Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead); } return buffer; } finally { if (stream.CanSeek) { stream.Position = originalPosition; } } } public class ImgInfo { /// <summary> /// 文件类型:身份证、营业执照、上岗证、其它证书 /// </summary> public int ImageType { get; set; } /// <summary> /// 文件扩展名 /// </summary> public string FileExtName { get; set; } /// <summary> /// 会话Id /// </summary> public string SessionId { get; set; } } }
如何用jQuery将辅助信息合并到二进制文件里一起上传到WCF
原文:http://blog.csdn.net/mole/article/details/45173699