【问题标题】:Upload file as JSON to Python webserver将文件作为 JSON 上传到 Python 网络服务器
【发布时间】:2019-02-06 14:05:03
【问题描述】:

我想将文件作为 JSON 从客户端上传到 Python 网络服务器 (Tornado) 并将其保存在服务器上。这是我的简化设置:

客户端 HTML:

<input type="file" id="myFile" onchange="fileChange" />

客户端JS:

function fileChange(event) {
    const file = event.target.files[0];
    const fileReader = new FileReader();
    fileReader.onload = (e) => uploadFile(e.target.result, file.name);
    fileReader.readAsText(file);
}

function uploadFile(fileContent, fileName) {
    const data = {fileContent, fileName};
    axios.post('http://localhost:8080/api/uploadFile', JSON.srtingify(data));
}

Python 网络服务器:

class UploadFileHandler(tornado.web.RequestHandler):

    def post(self):
        requestBody = tornado.escape.json_decode(self.request.body)
        file = open(requestBody["fileName"], "w+")
        file.write(requestBody["fileContent"].encode("UTF-8"))
        file.close()
  1. 所有上传的文件都是空的(PDF 中的空白页,JPG 文件类型“不支持”,Word 文件无法打开),并且几乎是原始文件的两倍。我该如何解决这个问题?
  2. 有没有办法改进这个设置?

【问题讨论】:

  • 显然你不应该重新编码你在 utf-8 中上传的任何内容,特别是如果文件是二进制文件。这没有任何意义。
  • 这听起来很合理,但没有编码我得到这个错误UnicodeEncodeError('ascii', u'%PDF-1.5\r\n%\ufffd\...\n318578\r\n%%EOF', 11, 15, 'ordinal not in range(128)')"

标签: javascript python html file upload


【解决方案1】:

您正在尝试上传二进制文件(word、jpg),序列化为 JSON,并将它们存储在服务器上。

要处理 JSON 格式的二进制数据,请先encode the binary data as base64,然后再调用JSON.stringify

像这样(未经测试):

function uploadFile(fileContent, fileName) {
    // Encode the binary data to as base64.
    const data = {
        fileContent: btoa(fileContent),
        fileName: fileName
    };
    axios.post('http://localhost:8080/api/uploadFile', JSON.stringify(data));
}

在服务器端,您需要从 JSON 反序列化,解码 base64 并以二进制文件mode 打开一个文件,以确保您正在写入磁盘的是上传的二进制数据。以文本模式打开文件需要在写入磁盘之前对数据进行编码,此编码步骤会损坏二进制数据。

这样的事情应该可以工作:

class UploadFileHandler(tornado.web.RequestHandler):

    def post(self):
        requestBody = tornado.escape.json_decode(self.request.body)
        # Decode binary content from base64
        binary_data = base64.b64decode(requestBody[fileContent])
        # Open file in binary mode
        with open(requestBody["fileName"], "wb") as f:
            f.write(binary_data)

【讨论】:

  • 非常感谢。这似乎是解决方案。在我的测试中,我需要先将 utf-8 文件转换为 ascii,然后再使用 btoabtoa(unescape(encodeURIComponent(fileContent)))。但后来我无法在 python 中正确解码文件您有什么建议?我尝试了 python encodedecode 方法的不同组合,但总是出现一些错误。
  • @cgdannie 从base64解码应该足够了,然后从utf-8解码得到的字节。如果这不起作用,请打开一个包含详细信息的新问题,我可以看看。
最近更新 更多