背景:
一个旅游网站收集当地的加油站信息,并在网站上通过地图标注。需要知道该加油站的坐标、名称。在地图网站手动搜索粘贴复制工作量比较大,就需要用个软件自动将搜索结果导出为xls或者xml格式的文件。
软件需求:
1.旅游网站采用51地图显示加油站等类型的显示地图,用51地图(互联网不同地图网站坐标系是不同的,估计是为了防止大浦洞导弹),因此数据源采用51地图。
2.wpf开发很久没碰了,时间要求紧,因此直接用asp.net写。
3.npoi从来没用过,因此考虑导出为xls。
4.需要将多个城市的搜索结果统一到一个表中导出(51地图仅支持每次搜索一个城市的关键词,见”地图服务->关键词搜索“)。
5.尽量用js完成功能,方便之后移植到wpf。
软件截图:
1.搜索框中输入搜索类型
2.搜索框旁边的按钮点击之后出现一个用fancybox做的弹窗,输入城市名称,用空格隔开。
3.搜索后左侧显示搜索结果,用jPages做个分页,右侧显示每一页的点(考虑到要搜索全西藏的加油站,因此用小比例尺)。点击列表中每一个点的按钮,可以地图放大到该点。暂时还没有把点删除功能加上。
4.搜索之后用ajax自动生成xml,存在tempXml文件夹下。
5.点击"生成xml"按钮,下载该xml表。
经验总结-JSON处理
1.地图搜索结果用一个自定义类型表示,将数据存储在一个数组中,在ajax调用时,将搜索结果用json传到后台。
function Coord(x, y, name,city) { this.x = x; //X坐标 this.y = y; //Y坐标 this.name = name; //加油站名称 this.city = city; //所在城市名称 }
2.将数组转换成JSON格式的函数
//我想生成的JSON格式为 //{"data":[{"x":111,"y":222,"name":"加油站1","city":“城市1”},
// {"x":112,"y":223,"name":"加油站2","city":“城市1”},
// // ....
// // {"x":113,"y":224,"name":"加油站1","city":“城市2”}
// ]} //数组转JSON字符串 function ArrToJson(arr) { var i,jsonstr; jsonstr = "{\"data\":["; for (i = 0; i < arr.length; i++) { jsonstr += "{\"x\"" + ":" + "\"" + arr[i].x + "\","; jsonstr += "\"y\"" + ":" + "\"" + arr[i].y + "\","; jsonstr += "\"name\"" + ":" + "\"" + arr[i].name + "\","; jsonstr += "\"city\"" + ":" + "\"" + arr[i].city + "\"},"; } jsonstr = jsonstr.substring(0, jsonstr.lastIndexOf(',')); jsonstr += "]}"; return jsonstr;
3.调用jquery的$.ajax方法。这里需要注意几个细节:
var p = ArrToJson(arrPoi); var p2 = eval('('+p+')'); $.ajax({ url: '/bll/WriteXml.ashx', type:'post', //contentType: "application/json;charset:utf-8;", dataType: 'json', //data:p2, data: { data: p, type: Words }, success: function () { } });
网上看到用eval('('+value+')');把json格式的字符串转为object,再传值,但是我无论如何也失败了,所以干脆用字符串传递。还有个问题就是contentType若为application/json的话,也无法在后台获取到参数。我考虑了几种组合排除,比如用eval先转为objec后,contentType用application/json;或者contentType用application/json,参数用JSON字符串;或者data直接写为“data:p”或“data:P2”。都没有成功,原因始终没有弄明白。
4.后台获取到参数后,将json格式的字符串解读。
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Utilities; /// <summary> /// JSON转换 /// </summary> /// <param name="json"></param> /// <returns></returns> public static List<Coords> TransJson(string json) { JObject jo = JObject.Parse(json); List<JObject> data = jo["data"].Children<JObject>().ToList(); List<string> xCoord = data.Values<string>("x").ToList(); List<string> yCoord = data.Values<string>("y").ToList(); List<string> name = data.Values<string>("name").ToList(); List<string> city = data.Values<string>("city").ToList(); List<Coords> Coords = new List<Coords>(); for (int i = 0; i < xCoord.Count; i++) { Coords coord = new Coords(); coord.X = xCoord[i]; coord.Y = yCoord[i]; coord.name = name[i]; coord.city = city[i]; Coords.Add(coord); } return Coords; }
这里使用的是newtonsoft.json库,在.NET3.5之后,加入了linq的支持。说实话用jsonConvert没搞明白,看了自带的DEMO之后,觉得如果是将JSON格式翻译,用linq最直观,数据操作也好弄;如果是在后台要把数组或者其他数据类型转为JSON格式的话,用JavaScriptConvert.SerializeObject最方便,一句话搞定。
经验总结-文件上传下载
1.文件上传
后台就不说了,主要说说ajax传文件的问题。之前用$.ajax传文件总是失败,后来查了下才知道ajax是无法传输文件的,必须在页面中加一个隐藏的frame然后响应该frame里面的方法(大概思路)。这么弄挺麻烦的,幸好有现成的插件,jquery form(下载),用它的.ajaxSubmit方法
<form id="FileForm" method="post" enctype="multipart/form-data"> <p> <input type="file" name="FileSelect" id="FileSelect" /></p> <p> <input type="button" value="" id="loadExcel" /></p> </form>
//点击按钮后响应该事件 //上传文件 function upLoadFIle() { $('#FileForm').ajaxSubmit({ url: '/bll/ReadExcel.ashx', success: function (data) { alert(data); } }); }
2.文件下载
弄了半天没弄出来,总结出一句话来,ajax没法文件下载!
string fileName=Session["fileName"].ToString(); string virPath = Session["filePath"].ToString(); //以文件的形式下载文件 string phyPath = Server.MapPath(virPath);//路径 FileInfo fi = new FileInfo(phyPath); Response.Clear(); Response.ContentType = "application/ms-download"; //context.Response.ContentType = "application/octet-stream"; Response.AddHeader("Content-Type", "application/octet-stream"); //context.Response.AddHeader("Content-Transfer-Encoding", "binary"); Response.Charset = "utf-8"; //context.Response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8"); //通知浏览器下载文件而不是打开 Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(fileName + ".xml")); Response.WriteFile(fi.FullName); Response.Flush(); Response.End();