最近在测试新上线的ANSiLib.COM站点的下载功能时,偶然发现下载下来的ANSI文件竟然无法正常显示,经过与原始文件对比发现,二者相差很大,下载下来的文件丢失了很多ANSI代码,经过多方分析,发现是由于当初上传文件内容的时候对内容编码的简单处理,导致数据的丢失,现记录如下。
在迁移NFODB.CN到ANSiLib的过程中,由于ANSI文件是通过远程POST到GAE站点上去的,由于两边的服务器默认编码都是UTF-8,Python的urllib库在POST数据的时候,默认会将数据转换成为Unicode的编码格式上传到服务器。而ANSI文件通常是采用CP437的编码格式,而程序里如果不加说明的话,Python程序会直接将读入字符串的ANSI文件内容当成UTF-8的编码,这样在转换到Unicode编码的过程中就会导致数据的丢失。原来的程序在本地端是简单地将ANSI文件读入到一个str字符串中,然后直接通过urllib库POST到服务端,在服务端仅仅简单地将收到的Unicode字符串进行了一次encode('utf-8'),就存入了数据库里,这样再从服务器端下载下来的数据就不再是当初CP437的编码格式了,当然也就无法正常显示了。
找到了原因,修改就容易了:
首先将读入str字符串的ANSI数据先在本地端编码成UTF-8的格式
data.decode('cp437').encode('utf-8')
然后POST数据到服务端,在服务端将收到的Unicode格式的数据还原成CP437编码格式
data.encode('cp437')
再将还原好的数据存入Datastore,在下载文件的时候,从Datastore里取回文件数据,直接吐给浏览器就好了
self.response.headers["Content-Type"] = "application/octet-stream"
self.response.headers["Cache-Control"] = "public, max-age=2592000"
self.response.headers.add_header("Expires", "31 December 2012 23:59:59 GMT")
self.response.headers.add_header("Content-Transfer-Encoding", "binary")
self.response.headers.add_header("Content-Disposition", "attachment", filename=download_filename)
self.response.headers.add_header("Content-Length", str(len(data)))
self.response.out.write(data)
经过这样改造,测试下载下来的文件与源文件完全一致,接下来的工作就是要全部重新上传ANSI文件数据,工作量巨大啊!!!
原来已经被网络爬虫爬下来了的错误的文件,不知道什么时候才会更新了,阿弥陀佛⋯⋯罪过罪过⋯⋯
Recent Comments