在网页端实现将Graphics以shp格式输出到本地,有幸google到了一点思路:
- 博客1:http://blog.roktech.net/blog/downloading-user-generated-graphics
- 博客2:https://nordpil.com/blog/js2shapefile/
- 讨论1:https://gis.stackexchange.com/questions/77109/json-to-shapefile-in-javascript
分析:
- 创建GP服务,属性字段是固定的,无法再添加;
- js2shapefile是比较合适的,但网上直接下载的源码并不支持中文,且字段格式是用typeof确定,并不科学;
- 最终决定对js2shapefile源码做适当修改。
完善:
(1)中文编码
源代码中对字符串使用charCodeAt()方法,读取该字符的Unicode编码,使用setUint8写入1个字节。
if (dataType == "C" || dataType == "") { if (fieldLength == 0) { continue; } if (typeof(attValue) !== "string") { // just in case a rogue number has got in... attValue = attValue.toString(); } if (attValue.length < fieldLength) { attValue = attValue.rpad(" ", fieldLength); } // doesn't matter if it's too long as we will only write fieldLength bytes for (var writeByte = 0; writeByte < fieldLength; writeByte++) { dbfDataView.setUint8(currentOffset, attValue.charCodeAt(writeByte)); currentOffset += 1; } }
charCodeAt()方法可以读取字符的 Unicode 编码,返回值是 0 - 65535 之间的整数,但setUint8明显是不合理的,对中文并不适用。
此外,通过由ArcGIS保存的SHP中的dbf文件,通过小程序读取字节,发现在dbf中采用的是UTF-8。unicode一个中文字符占2个字节,而UTF-8一个中文字符占3个字节。具体可参考http://www.cnblogs.com/yuguangchuan/p/4310952.html。
参考http://www.jb51.net/article/87418.htm,最终修改如下:
var index = 0; for (var writeByte = 0; writeByte < attValue.length; ) { var result = writeUTF(attValue[index]); // => [0, 3, 228, 184, 173] //currentOffset += result[1]; for (var codeIndex = 0; codeIndex < result[1]; codeIndex++) { dbfDataView.setUint8(currentOffset, result[2 + codeIndex]); currentOffset += 1; writeByte++; } index++; } }
(2)字段类型
修改switch (typeof (attvalue))部分,由用户自定义类型allAttributes。基本四种类型如下:
// 遍历字段组合,构建dbf所需要的对象 var allAttributes = {}; $.each(me._fieldNames, function (index, field) { var type = field.fieldType; var attribute = field.fieldName; switch (type) { case "INT": allAttributes[attribute] = { type: 'N', length: 18 } break; case "DOUBLE": allAttributes[attribute] = { type: 'N', length: 18, scale: 8 } break; case "DATE": allAttributes[attribute] = { type: 'D' } break; case "STRING": allAttributes[attribute] = { type: "C", length: 254 } break; }; });
完善这两点后,基本可以得到想要的结果。