如何将通过浏览器上传的文件转换为字节?
How to convert uploaded via browser file to bytes?
我需要将图像(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 -> 字节的字节。
我认为这是一个 XY 问题,因为您实际上想知道如何将文件直接传递到请求中,而对于如何将 base64 转换为字节的问题,您已经走错了路。所以最好退一步,因为有更直接的解决方案。
我在这里看到两个问题:
您正在将文件作为数据读取 URL,即使您需要原始格式的文件。我的建议是使用 readAsArrayBuffer
instead. But actually you don't have to read or convert the data at all - you could just pass the imageFile
directly into axios.put
. This should work because File
inherits from Blob
并且 axios 接受 Blob
s 作为正文。
您将 { 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)
})
我需要将图像(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 -> 字节的字节。
我认为这是一个 XY 问题,因为您实际上想知道如何将文件直接传递到请求中,而对于如何将 base64 转换为字节的问题,您已经走错了路。所以最好退一步,因为有更直接的解决方案。
我在这里看到两个问题:
您正在将文件作为数据读取 URL,即使您需要原始格式的文件。我的建议是使用
readAsArrayBuffer
instead. But actually you don't have to read or convert the data at all - you could just pass theimageFile
directly intoaxios.put
. This should work becauseFile
inherits fromBlob
并且 axios 接受Blob
s 作为正文。您将
{ 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)
})