V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
matepi
V2EX  ›  程序员

上传中文文件名文件- Linux 存储并本地 shell 等处理文件-回显文件名列表-按原文件名下载文件 的需求中,最优雅的编解码方式是什么?

  •  
  •   matepi · 225 天前 · 1022 次点击
    这是一个创建于 225 天前的主题,其中的信息可能已经有所发展或是发生改变。
    需求:

    Steps
    1) 用户通过浏览器上传文件至 linux 服务器,需支持原文件名带中文文件名,列表回显至用户
    2) 文件在 linux 服务器上存储后,自动触发,通过 shell 脚本作为入口,进行文件的处理
    3) 用户可以再浏览器上,看到已处理完成的原文件名+".result.txt"的文件,进一步下载回用户本地

    问题:

    直接上传文件名至服务器端,可能因 linux 服务器本地编码不同等原因直接就中文->??了。在需支持各种服务器编码情况下,进行中文文件名的编码是必须的。

    但,哪种编码为最优? BASE64 ? HTML entity ?或其他?

    BASE64 应该可以在 http 下载 http head 中,被浏览器下载文件过程中直接解码;
    而 HTML entity 可以在浏览器页面回显中,被浏览器页面渲染直接解码;
    同时这两种编码是否在 linux shell 调用过程中有需要转义,又多一步转义编码?

    但同时隐忧,解码尽量利用浏览器行为,是否会有浏览器不兼容性的隐忧,或许不如就老老实实手动编码?


    目的:

    寻求一个最优雅文件名编码形式,适应上传后、服务器端存储、服务器端 linux shell 处理、浏览器回显、浏览器下载等多种场景下,编解码最少、最优雅、同时一定程度上考虑浏览器兼容性的中文文件名编码转化方式。
    第 1 条附言  ·  225 天前
    许多网友发言还是针对上传后的处理有些反对意见,可能确实是我需求表达不清,再补充更新下:

    需求:

    实现一个较为通用、对环境依赖小的可广泛使用的功能模块
    Steps
    1) 用户通过浏览器上传数据 txt 文件至 linux 服务器,需支持原文件名带中文文件名,并列表回显至用户
    2) 文件上传后在 linux 服务器上存储 txt 文件后,上传处理进程自动触发后续数据清洗/文本处理/加载到数据库等、可由二次开发人员定制的处理流程;这些处理流程需支持通过 shell 脚本作为总调起入口,进行一系列对上传文件的处理
    3) 用户可以再浏览器上,看到已处理完成的原文件名+".result.txt"的文件,进一步下载回用户本地
    24 条回复    2023-09-18 16:54:07 +08:00
    jifengg
        1
    jifengg  
       225 天前
    “支持各种服务器编码”这个是真实情况还是臆想出来的?
    服务器统一使用 UTF8 编码不行吗?

    服务器端统一了,那全流程都是 utf8 编码,不会有问题的。(不要用 UTF8 BOM 头!!!)
    mengzhuo
        2
    mengzhuo  
       225 天前
    "通过 shell 脚本作为入口"

    贵司是架构和安全都是吃干饭的么?要提供 webshell 给用户?随便一个提权命令都可以搞废你们这服务器。
    matepi
        3
    matepi  
    OP
       225 天前
    @jifengg 做的是框架性通用性功能。如果要求服务器统一编码会限制通用性功能的使用范围。设计思路上是能减少一个用户要求,就减少一个用户环境要求。

    而且,全流程 utf-8 会要求,不单单是服务器了。要求前端页面等也得 utf-8 、才能客户端浏览器以 utf-8 处理,这种传染形式,就更不利于框架性功能的推广了。
    matepi
        4
    matepi  
    OP
       225 天前
    @mengzhuo 可能是我表达不清? txt 文件上传后,服务器端自动触发开发编写的 shell ,去进行对 txt 文件的数据处理。不是 webshell ,我不觉得这个有什么安全问题。
    NessajCN
        5
    NessajCN  
       225 天前
    @matepi
    第一,现在全程 utf-8 完全没问题
    第二,你实在要其他编码,那就让前端把编码方式一起发回来就是了
    NessajCN
        6
    NessajCN  
       225 天前
    @matepi 迷惑行为,既然是服务端行为,那你服务端用的语言没有 fs 写文件模块吗,为啥要调用 shell ?
    matepi
        7
    matepi  
    OP
       225 天前
    @NessajCN 大概确实是我需求部分表达有问题了。服务器端调用 sed 、sqploader 、或其他自有工具等形式,对数据的文本清洗处理等后再加载。其中用 shell 作者为先后处理/加载的过程的总入口,我理解是最通用的一种文件上传处理框架中,需支持的入口模式了。我不能理解,fs 能够作为数据文件清洗/处理/加载的总入口吗?
    NessajCN
        8
    NessajCN  
       225 天前
    @matepi
    「 fs 能够作为数据文件清洗/处理/加载」
    不然咧?
    matepi
        9
    matepi  
    OP
       225 天前
    @NessajCN 求教了,如果我要用 fs 做一个:

    1 、显示类似 sed 去掉数据文件行末和文末空格空行;

    2 、在完成步骤 1 后,实现类似 sqlloader 工具,将处理后文件导入指定数据库。

    这个应该如何做到呢?
    NessajCN
        10
    NessajCN  
       225 天前
    const data = await fs.readFile("test.txt", "utf8")
    const data_trim() = data.trim()

    // 写文件
    await fs.writeFile("test_trim.txt")

    // 数据库
    matepi
        11
    matepi  
    OP
       225 天前
    @NessajCN 还有略的部分,看来这个要处理的内容还是会比较多的。利用 linux 命令和现有 sqlloader 工具就能实现的,差不多几行脚本和工具调用命令,就能实现的话;个人还是感觉不大会有二次开发人员,去首选自己开发这些代码了。何况相比 shell ,还有多个 nodejs 环境基础依赖。nodejs 较 shell 来说,不是通用入口的优选。
    NessajCN
        12
    NessajCN  
       225 天前
    @matepi
    ...因为你没说用啥语言所以我就拿 node 举个例子
    你后端接口总是有个语言环境的啊,用那个的 fs/os/或什么模块不就没其他依赖了
    matepi
        13
    matepi  
    OP
       225 天前
    @NessajCN 后端要交出这块数据处理调用给到二次开发手里的,既然是二次开发,就要选择最没有依赖、人人都能用起来的语言环境=>我选择 shell 作为首先要支持的语言环境、或者由二次开发选择通过 shell 再调用他们自己研发的语言代码的入口。
    jptx
        14
    jptx  
       225 天前   ❤️ 1
    设计一张任务表或者类似的东西,用户上传时,相当于提交了一个任务。任务中可以有很多属性,比如原始文件名、任务类型、用户 ID 、任务创建时间、任务开始时间、任务结束时间、任务状态、任务简要日志等。
    用户上传文件之后,自动在任务表中提交任务,记录下文件的原始名称。磁盘上实际存储文件时使用任务 ID 去作为文件名,这样你调用脚本时不需要关心原始文件名了,全程只需要关心任务 ID 。脚本执行完成之后根据任务 ID 去更新任务状态。结果文件保存时也是只关心任务 ID 。
    用户下载结果文件时,在下载接口中根据任务中的原始文件名实时生成结果文件名。这样结果文件也不需要关心原始文件名了。
    根据这个任务表,后面还可以增加更多的业务,比如批量导入、对接其他系统自动导入、重试导入、导入历史等等。
    ysc3839
        15
    ysc3839  
       225 天前 via Android
    base64 ,因为 shell 下直接用 base64 -d 就能解码。html 那些连解码工具都没。
    hzjseasea
        16
    hzjseasea  
       225 天前
    好奇用 shell 怎么将数据加载到数据库的.. 还有文本处理 awk sed grep 这三件套处理简单的文本和数据清洗,一旦复杂起来,不专业点的老运维 review 都得半天.. 个人感觉..
    matepi
        17
    matepi  
    OP
       225 天前
    @jptx 恩,这就是比老老实实手动编码的思路,更老老实实的思路了。确实有道理,展示层进出的时候就弄掉,中间一路干净也是是正道。
    matepi
        18
    matepi  
    OP
       225 天前
    @hzjseasea 因为稍微正经点的数据库,都会有在 shell 下能够直接用起来的,配套文本导入工具/命令行功能。Oracle 的 sqlldr ; MySQL 的 LOAD DATA ; PG 的 COPY FROM 等等。原生直接对接数据库,速度快,不用再研发。数据库运维掌握这些工具是必备技能,出了啥问题也是运维和数据库公司支持方面搞定。(其实多少也是为了研发可以推点活到运维吧)
    mengzhuo
        19
    mengzhuo  
       224 天前
    @matepi 那也很可怕了……注入了解一下?输入数据必须经过程序完全转义和校验以后才能进入数据库的,真是不怕一锅端。
    matepi
        20
    matepi  
    OP
       222 天前 via iPhone
    @mengzhuo 这正是用各类 loader 工具而不用自己代码程序的好处,各类 loader 工具和程序 sql 的差异了解下?
    mengzhuo
        21
    mengzhuo  
       222 天前
    @matepi 我随便塞一个远程下载+反向 shell 怎么办?能上传任何逻辑就是死啊,回头你试试看公布一下地址,估计不超过 1 小时就被爆。
    matepi
        22
    matepi  
    OP
       222 天前
    @mengzhuo 上传 shell 又不会被执行的……只会被 sed 处理、按 loader 工具按照预定的分割规则进行分隔符切割/定长分割处理后由工具入库,工具也不会用 SQL 引擎解析其中文字。读帖首先看题干看题干看题干…
    mengzhuo
        23
    mengzhuo  
       222 天前
    @matepi 不过滤么?这是想元编程来偷懒?我们之前搞手游的时候就出过这样的安全漏洞,直接搞挂整个业务(幸好是内部上传接口而已)。

    就按你说的 sed+loader ,这个最简单的例子,一个带 header csv ,要 insert 每一行的话,不检验和过滤,分分钟教做人
    ```
    item,count
    id1,1
    "; drop table user, 2
    ```

    算了……好言难劝该死鬼,我坐等你来发挨攻击的帖子。
    matepi
        24
    matepi  
    OP
       222 天前
    @mengzhuo

    哎,数据库 loader 工具不是又依赖 insert 的…
    不是我不懂 SQL 注入,而是你不知道哪些做法不会引起注入……

    SQL 注入的优良解决方式不是依赖过滤的,而是依赖 SQL 执行侧上正确的变量绑定、包括我上面所说的使用数据库厂商的文本数据 loader 工具。这些是不会引起注入的。

    过滤不是个完善的实现。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3018 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 13:35 · PVG 21:35 · LAX 06:35 · JFK 09:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.