JS文件上传:检测编码

5
所以,我正在尝试使用AngularJS在前端和NodeJS在后端编写CSV文件导入器。 我的问题是,我不确定传入的CSV文件的编码方式。有没有一种自动检测它的方法?
我首先尝试使用FileReader.readAsDataURL()在Node中进行检测。但是文件内容将被Base64编码,因此我无法这样做(当我解码文件时,我已经需要知道编码方式)。 如果我使用FileReader.readAsText(),我也需要事先知道编码方式。但是,在初始化FileReader之前也无法这样做,因为实际文件对象似乎不包括文件内容。
我的当前代码:
generateFile = function(file){
    reader = new FileReader();
    reader.onload = function (evt) {
        if (checkSize(file.size) && isTypeValid(file.type)) {
            scope.$apply(function () {
                scope.file = evt.target.result;
                file.encoding = Encoding.detect(scope.file);
                if (angular.isString(scope.fileName)) {
                    return scope.fileName = name;
                }
            });
            if (form) {
                form.$setDirty();
            }
            scope.fileArray.push({
                name: file.name,
                type: file.type,
                size: file.size,
                date: file.lastModified,
                encoding: file.encoding,
                file: scope.file
            });
            --scope.pending;
            if (scope.pending === 0){
                scope.$emit('file-dropzone-drop-event', scope.fileArray);
                scope.fileArray = [];
            }
        }
    };
    let fileExtExpression = /\.csv+$/i;
    if(fileExtExpression.test(file.name)){
        reader.readAsText(file);
    }
    else{
        reader.readAsDataURL(file);
    }
    ++scope.pending;
}

这个问题是不是完全无法解决?或者我做错了什么?我甚至尝试使用FileReader.readAsArrayBuffer()来解决这个问题,并从中提取文件头,但这对我来说太过复杂,或者似乎并没有起作用。


现在的问题是,为什么文件内容要进行base64编码?这没有太多意义。文件应该是字节存储的,你可以直接将字节写入文件。在这种情况下,将字节流编码为base64除了使文件变大并减慢读写速度之外,没有任何作用。 - Tomalak
是的,我知道。所以现在base64只用于上传图片。因此,对于我的CSV文件,我想将其作为文本读取。但是,如果我不知道如何动态设置FileReader.readAsText()的编码参数。 - DCH
你上传图片时其实不需要使用base64。base64只在需要在不支持原始字节的环境中传输(或存储)任意字节时才需要使用,典型的情况是基于字符串的格式,例如JSON或XML。HTTP可以轻松传输原始字节,因为这就是它被设计出来的目的。那么...为什么还要使用base64呢? - Tomalak
因为这就是 FileReader.readAsDataURL() 的工作方式... 这有点偏离主题了 ;-). - DCH
我尝试使用readAsArrayBuffer...,但是当我通过http请求将其传递到正文中时,它作为空对象到达,无法用于缓冲区。关于您的第一条评论:当我使用Buffer.toString解码base64字符串时,我仍然需要知道原始编码,这就是我在那个时候不知道的。 - DCH
显示剩余8条评论
2个回答

4

在Node中:const jschardet = require('jschardet'); jschardet.detect(await require('fs/promises').readFile(fileName)),例如:jschardet.detect(await require('fs/promises').readFile('test.txt')),输出: { encoding: 'UTF-8', confidence: 0.99 } - mikey

3
你可以尝试这个:
$ npm install detect-file-encoding-and-language

然后可以这样检测编码:

// index.js

const languageEncoding = require("detect-file-encoding-and-language");

const pathToFile = "/home/username/documents/my-text-file.txt"

languageEncoding(pathToFile).then(fileInfo => console.log(fileInfo));
// Possible result: { language: japanese, encoding: Shift-JIS, confidence: { language: 0.97, encoding: 1 } }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接