首页 > 解决方案 > 如何将通过浏览器上传的文件转换为字节?

问题描述

我需要将图像(File对象)作为字节上传到服务器。图像由用户通过输入字段上传到浏览器。

我的问题是图像必须转换为字节,我找不到如何在 JS 中完成。

下面是可以正常工作的python代码。

response_with_image = requests.get('some-url.png')
bytes_of_image = response_with_image.content # ->> b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x03R\x00\x00\x02\xbc\x08\x02\x00\x00\x00j}\x19\x16\x00\x00\x00\tpHYs\x00\x00\x0fa\x00\x00\x0fa\x01\xa8?\xa7i\x00\x00 \x00IDATx\x9c\xec\xbd\xbf\xcbuKr\x1eZ\xfd\xce\t,s\xb9\xfa\x17\x8ep\xa2@X\xe0\xbf`\x06\'g\xb8\xa9\xfe\x02i\x12#\xb8\xd1\x0c\x0e\'6\x9a\xe4\xfe0JfP$.\xf7"Pdt\x121\x03J\x84\xc0\xd8\xe0\t&\x11:\x18\x8c\x13e\x86\x19\x07:\xbbo\xf0~o\x9fZ\xf5<\xf5tu\xaf\xbd\xdf\xef\xdb3\xabh\x9a\xa7\xaa\xab\xaa{U\xf7\xea\xae\xd3\xeb\xdd\xdfi\xbdw\xbb\xe8\xa2\x8b.\xba\xe8\xa2\x8b.\xba\xe8\xd7\x9d^>\xf6......'

r = requests.put(url_to_upload_file, headers={"Content-Type": "image/png"}, data=bytes_of_image)

目前我可以用 JS 实现的最佳效果如下 - 代码创建了一个大小不正确(90 KB 而不是 66 KB)和正确类型的文件。当我检查上传的文件时,浏览器不会将其识别为图像,显然是因为我上传的是 base64 而不是字节。

const urlToUploadFile = 'url-provided-by-service'

const imageFile = files[0]
const reader = new FileReader()
reader.onloadend = function () {
    const result = reader.result // data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAsUAAAQJCAYAAAAuMXXtAAAgAElEQVR4nOzdfWxTd573/f6....

    await axios.put(
        urlToUploadFile,
        { data: result },
        { headers: { 'Content-Type': 'image/png' } }
    ).then(response => {
        console.log('response:', response)
    })

reader.readAsDataURL(imageFile)

我找不到如何imageFile直接转换为imageFile-> base64 -> 字节的字节。

标签: javascriptfile-uploadbyte

解决方案


我认为这是一个 XY 问题,因为您实际上想知道如何将文件直接传递到请求中,以及如何将 base64 转换为字节的问题,您已经走错了路。所以最好退后一步,因为有一个更直接的解决方案。

我在这里看到两个问题:

  1. 即使您需要原始格式的文件,您也正在将文件作为数据 URL 读取。我的建议是readAsArrayBuffer改用。但实际上您根本不需要读取或转换数据 - 您可以imageFile直接将axios.put. 这应该有效,因为File继承自Blob并且 axios 接受Blobs 作为主体。

  2. 您正在传递{ data: result }而不是result作为正文参数传递给axios.put. 结果是 axios 将看到一个带有键data和一些值的对象并尝试对其进行编码,但实际上您似乎正在尝试直接上传原始文件(也根据您的Content-Type. 因此,显然使用axios.put(url, theData, { headers: ... })而不是axios.put(url, { data: theData }, { headers: ... })应该修复它。

顺便说一句,您也可以从imageFile.type.


底线是以下代码应该可以工作:

const urlToUploadFile = 'url-provided-by-service'

const imageFile = files[0]

await axios.put(
    urlToUploadFile,
    imageFile,
    { headers: { 'Content-Type': imageFile.type } }
).then(response => {
    console.log('response:', response)
})

推荐阅读