PapaParse获取URL文件编码错误问题解决

继续PapaParse的坑,这个插件虽说强大,可以快速将CSV文件转为JSON格式来渲染表格,但是某些地方真的让人很难受,比如它自带的encoding配置只能对通过input上传的本地文件起作用,而通过URL远程取到的文件不支持...

优化插件是做不到,那办法只有一个了,先用XMLHttpRequest()获取到文件,然后再用FileReader()改变文件的编码,最后用PapaParse直接解析。

要改变文件编码得先知道文件类型:

//解析文件类型
function checkEncoding(path) {                        //path是文件的路径
    return new Promise(function (resolve) {           //使用Promise对象避免出现同异步问题
        $.get(path, function (data, status) {
            if (status == 'success') {
                var encoding = jschardet.detect(data);
                encoding = encoding.encoding;
                if (encoding === 'windows-1252') {    //这边根据自己的配置更改即可
                    encoding = 'GB2312';
                } else if (encoding === 'ascii') {
                    encoding = 'UTF-8';
                }
                resolve(encoding);                    //最后返回文件编码类型
            }
        });
    });
}

这边使用了jschardet插件来实现,好处是在前端就能应对大多数情况,但有些文件会识别失败...

附上后端解决办法,用C#编写:

using System;
using System.IO;
using System.Text;
using System.Web;

public class CheckEncoding : IHttpHandler {

    public void ProcessRequest(HttpContext context) {
        context.Response.ContentType = "text/plain";
        var path = context.Request["path"];
        try {
            string ReadPath = HttpContext.Current.Server.MapPath("~/" + path + "");
            byte[] bom = File.ReadAllBytes(ReadPath);
            var encoding = GetBytesEncoding(bom);
            context.Response.Write(encoding.BodyName);
        } catch (Exception e) {
            context.Response.Write("{\"fail\":\"" + e + "\"}");
        }
    }

    public static Encoding GetBytesEncoding(byte[] bs) {
        int len = bs.Length;
        if (len >= 3 && bs[0] == 0xEF && bs[1] == 0xBB && bs[2] == 0xBF) {
            return Encoding.GetEncoding("gbk");
        }
        int[] cs = { 7, 5, 4, 3, 2, 1, 0, 6, 14, 30, 62, 126 };
        for (int i = 0; i < len; i++) {
            int bits = -1;
            for (int j = 0; j < 6; j++) {
                if (bs[i] >> cs[j] == cs[j + 6]) {
                    bits = j;
                    break;
                }
            }
            if (bits == -1) {
                return Encoding.GetEncoding("gbk");
            }
            while (bits-- > 0) {
                i++;
                if (i == len || bs[i] >> 6 != 2) {
                    return Encoding.GetEncoding("gbk");
                }
            }
        }
        return Encoding.UTF8;
    }

    public bool IsReusable {
        get {
            return false;
        }
    }

}

gb2312加utf-8格式就能解决我这边绝大多数的中文编码问题,在无BOM码的情况下只判断是否为utf-8还是相对容易点的;

然后开始解析CSV文件:

//解析CSV
function parseCSV(path, encoding) {                   //(路径,编码类型)
    return new Promise(function (resolve) {           //同样使用Promise()防止异步问题
        //通过ajax请求到文件
        let request = new XMLHttpRequest();
        request.open('GET', path, true);              //目标url
        request.responseType = 'blob';
        request.onload = () => {
            let file = request.response;
            let reader = new FileReader();
            reader.readAsText(file, encoding);        //编码
            reader.onload = () => {
                Papa.parse(reader.result, {           //主角登场(配角太抢戏了...
                    complete: function (results) {
                        resolve(results.data);
                    }
                });
            }
        }
        request.send();
    })
}

小小的demo:

async function main(path){   //(路径)  //得在async中使用await 
    //获取文件格式
    let encoding = await checkEncoding(path);
    //获取标准答案
    let criteriaAnswer = await parseCSV(path, encoding);
    //渲染表格
    paintingTable(criteriaAnswer,"teacherPaperAnswer"); //用id定位渲染目标
}

赠送一个JSON文件渲染CSV表格:

//渲染表格
function paintingTable(File, location) {
    $("#" + location + "").empty();
    let table = '<table class="table table-bordered" style="zoom:0.8";>';
    for (let j = 0; j < File.length; j++) {
        if (j == 0) {
            table += '<thead><tr style="white-space: nowrap;"><th scope="col">#</th>';
            for (let k in File[j]) {
                table += '<th scope="col">' + k + '</th>';
            }
            table += '</tr></thead><tbody style="white-space: pre;">';
        }
        table += '<tr><th scope="row" style="vertical-align: middle;">' + Number(j + 1) + '</th>';
        for (let k in File[j]) {
            table += '<td style="vertical-align: middle; padding:0 20px; border: inset;background:#FFFFFF;"><div style="text-align:left;">' + File[j][k] + '</div></td>';
        }
        table += '</tr>';
    }
    table += '</tbody>';
    $("#" + location + "").append(table);
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值