前言
最近项目中要做一些图片的存放功能,网上找了找WebApi的文件上传存放,用的挺多的是HttpPostedFileBase的方式,不过我希望是图片和数据都同时通过一个POST上传上来,所以这次我们改用的是MultipartFormDataStreamProvider的方式。
实现效果
代码实现
由于我这是在项目直接使用了,所以只把关键的东西介绍一下
通讯类介绍
返回类CResponse
请求类CRequest
数据表及对应类
数据表tVipMember_Pic
对应类CVipMemPic
///<summary> ///会员图片 ///</summary> [SugarTable("tVipMember_Pic")] public partial class CVipMemberPic { public CVipMemberPic(){
} /// <summary> /// Desc:会员编码 /// Default: /// Nullable:False /// </summary> [SugarColumn(IsPrimaryKey = true)] public string VipNO {get;set;}
/// <summary> /// Desc:照片序号 /// Default: /// Nullable:False /// </summary> [SugarColumn(IsPrimaryKey = true)] public int Photoidx {get;set;}
/// <summary> /// Desc:照片类型 /// Default: /// Nullable:True /// </summary> public string Phototype { get; set; }
/// <summary> /// Desc:照片 /// Default: /// Nullable:True /// </summary> public byte[] Photo {get;set;}
}
WebApi
定义会员图片Controller
上传会员图片Post
核心代码
/// <summary> /// 上传图片 /// </summary> /// <param name="user"></param> /// <returns></returns> [MsgRecordFilter] [Route("Uploadfile")] public async Task<CResponse<List<CVipMemberPic>>> Uploadfile() { CResponse<List<CVipMemberPic>> response = new CResponse<List<CVipMemberPic>>(); try { if (!Request.Content.IsMimeMultipartContent()) { response.ResId = -1; response.ResMsg = "通讯的数据有问题"; return response; } //指定要将文件存入的服务器物理位置 string root = HttpContext.Current.Server.MapPath("~/App_Data"); var provider = new MultipartFormDataStreamProvider(root);
//删除生成30天以上的文件 DateTime date = DateTime.Today.AddDays(-30); FileApi.DelFileFromDate(root, date);
//读取数据 await Request.Content.ReadAsMultipartAsync(provider);
//获取请求字符串 string json = provider.FormData["json"]; CRequest<string> req = JsonConvert.DeserializeObject<CRequest<string>>(json);
//校验签名 if (!TransSignApi.CheckRequestSignTs(req)) { response.ResId = -1; response.ResMsg = "通讯签名不正确!"; return response; }
//获取图片序列号 int vipidx = 1;
List<CVipMemberPic> pics = new List<CVipMemberPic>(); foreach (MultipartFileData file in provider.FileData) { FileStream fs = null; byte[] pReadByte = new byte[0]; try { fs = new FileStream(file.LocalFileName, FileMode.Open, FileAccess.Read); BinaryReader r = new BinaryReader(fs); //将文件指针设置到文件开 r.BaseStream.Seek(0, SeekOrigin.Begin); pReadByte = r.ReadBytes((int)r.BaseStream.Length);
//获取新的会员图片 CVipMemberPic pic = new CVipMemberPic(); pic.VipNO = req.ReqData; pic.Photoidx = vipidx; pic.Phototype = file.Headers.ContentDisposition.FileName; pic.Photo = pReadByte;
pics.Add(pic); vipidx++; } catch (Exception ex) { throw ex; } finally { if (fs != null) fs.Close(); } }
int count = VipMemberPicApi.SavePhoto(pics); if (count > 0) { response.ResId = 1; response.ResMsg = "成功上传" + count + "张图片"; response.ResData = pics; } else { response.ResId = -1; response.ResMsg = "图片未保存成功!"; response.ResData = null; } } catch (Exception ex) { response.ResId = -1; response.ResMsg = ex.Message; response.ResData = null; }
return response; }
}
下载会员图片Get
核心代码
/// <summary> /// 获取会员图片 /// </summary> /// <param name="req"></param> /// <returns></returns> [Route("Downloadfile")] public CResponse<List<CVipMemberPic>> GetVipPic( [FromUri] CRequest<string> req) { CResponse<List<CVipMemberPic>> response = new CResponse<List<CVipMemberPic>>();
try { //校验签名 if (!TransSignApi.CheckRequestSignTs(req)) { response.ResId = -1; response.ResMsg = "通讯签名不正确!"; return response; }
//获取会员 List<CVipMemberPic> pics = VipMemberPicApi.GetVipPic(req.ReqData); if (pics == null) { response.ResId = -1; response.ResMsg = "获取不到会员图片!"; response.ResData = null; } else { response.ResId = 1; response.ResMsg = "获取到" + pics.Count + "会员图片!"; response.ResData = pics; } } catch (Exception ex) { response.ResId = -1; response.ResMsg = ex.Message; response.ResData = null; }
return response; }
WinForm端调用
我们封装了一个Get和Post的调用类,这里我只把Get和Post上传的这块摘出来
WebapiHelper
Get方法
/// <summary> /// Get请求指定的URL地址 /// </summary> /// <typeparam name="T">返回的json转换成指定实体对象</typeparam> /// <param name="url">URL地址</param> /// <returns></returns> public static T GetWebAPI<T>(string url) where T : class, new() { T result = default(T);
using (HttpClient httpClient = new HttpClient()) { httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage response = httpClient.GetAsync(url).Result;
if (response.IsSuccessStatusCode) { Task<string> t = response.Content.ReadAsStringAsync(); string s = t.Result; string jsonNamespace = DeserializeObject<T>(s).ToString(); result = DeserializeObject<T>(s); } } return result; }
POST上传数据及图片的方法
/// <summary> /// Post请求指定的URL地址 /// </summary> /// <typeparam name="T">返回的json转换成指定实体对象</typeparam> /// <param name="url">URL地址</param> /// <param name="postData">提交到Web的Json格式的数据:如:{"ErrCode":"FileErr"}</param> /// <param name="filepath">文件地址</param> /// <returns></returns> public static T PostWebAPI<T>(string url, string postData, List<byte[]> byteses) where T : class, new() { T result = default(T);
HttpClientHandler httpHandler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip }; using (HttpClient httpClient = new HttpClient(httpHandler)) { using (var multipart = new MultipartFormDataContent()) { //加入Json数据 HttpContent dataContent = new StringContent(postData, Encoding.UTF8, "application/json"); dataContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { Name = "json" }; multipart.Add(dataContent);
//加入图片数据 foreach (byte[] imgBytes in byteses) { HttpContent byteArray = new ByteArrayContent(imgBytes); byteArray.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = imgBytes.Length.ToString() }; multipart.Add(byteArray); }
HttpResponseMessage response = httpClient.PostAsync(url, multipart).Result;
if (response.IsSuccessStatusCode) { Task<string> t = response.Content.ReadAsStringAsync(); string s = t.Result; //Newtonsoft.Json string jsonNamespace = DeserializeObject<T>(s).ToString(); result = DeserializeObject<T>(s); } } } return result; }
Form窗体
动态处理PictureBox的操作代码
#region FlowPanel操作 /// <summary> /// 初始化FlowPanel /// </summary> private void InitPnl() { flowpnl.Controls.Clear(); } /// <summary> /// 根据文件名显示图片 /// </summary> /// <param name="filename"></param> private void AddPic(string filename) { int counts = flowpnl.Controls.Count; int idx = counts == 0 ? 1 : counts + 1; PictureBox pic = new PictureBox(); pic.SizeMode = PictureBoxSizeMode.StretchImage; pic.ImageLocation = filename; pic.Tag = idx; pic.Name = "pic" + idx; pic.Width = 150; pic.Height = 150; flowpnl.Controls.Add(pic); } /// <summary> /// 根据图片byte数组显示图片 /// </summary> /// <param name="member"></param> private void AddPic(CVipMemberPic member) { int counts = flowpnl.Controls.Count; int idx = counts == 0 ? 1 : counts + 1;
PictureBox pic = new PictureBox(); pic.SizeMode = PictureBoxSizeMode.StretchImage; pic.Image = ImgbyteApi.BytesToImage(member.Photo); pic.Tag = member.Photoidx; pic.Name = "pic" + member.Photoidx; pic.Width = 150; pic.Height = 150; flowpnl.Controls.Add(pic); } /// <summary> /// 删除图片 /// </summary> /// <param name="picture"></param> private void DelPic(PictureBox picture) { foreach (PictureBox control in flowpnl.Controls) { if (control.Name == picture.Name) { flowpnl.Controls.Remove(control); } } } #endregion
上传图片
private void btnupload_Click(object sender, EventArgs e) { lblmsg.Text = ""; if (flowpnl.Controls.Count > 0) { List<byte[]> bytes = new List<byte[]>(); foreach (PictureBox item in flowpnl.Controls) { bytes.Add(ImgbyteApi.ImageToBytes(item.Image)); }
CRequest<string> request = new CRequest<string>(); request.ReqData = "00001";
TransSignApi.CreateRequestSign(ref request);
string poststr = JsonConvert.SerializeObject(request);
string transurl = textBox1.Text + "/Uploadfile"; try { CResponse<List<CVipMemberPic>> response = WebapiHelper.PostWebAPI<CResponse<List<CVipMemberPic>>> (transurl, poststr, bytes); lblmsg.Text = response.ResMsg; } catch (Exception ex) { lblmsg.Text = ex.Message;
} } }
下载图片
private void btndownload_Click(object sender, EventArgs e) { //初始化 lblmsg.Text = ""; InitPnl();
CRequest<string> request = new CRequest<string>(); request.ReqData = "00001";
TransSignApi.CreateRequestSign(ref request);
string url = textBox1.Text + "/Downloadfile" + "?Sign=" + request.Sign + "&Ts=" + request.Ts + "&ReqData=" + request.ReqData;
try { var response = WebapiHelper.GetWebAPI<CResponse<List<CVipMemberPic>>>(url); lblmsg.Text = response.ResMsg; if (response.ResId == 1) { foreach (var item in response.ResData) { AddPic(item); } } } catch (Exception ex) { lblmsg.Text = ex.Message;
} }
操作效果
选择本地图片
下载图片
服务端有三张图片,我们本地四张,所以点击下载后只显示服务端存在的三张图片