node.js - 上传的图像节点损坏
问题描述
我通过 Next.js API 路由上传的图像已损坏。我正在使用强大的。
从我的 React 组件中,我通过这些函数提交了一个表单:
const fileUpload = async (file: File) => {
const url = '/api/image'
const formData = new FormData()
formData.append('file', file)
const config = {
headers: {
'content-type': 'multipart/form-data',
},
}
const response = await axios.post(url, formData, config)
const { data } = response
return data
}
const handleSubmit = async (event: React.SyntheticEvent) => {
const url = '/api/post'
if (files) {
// ignore
fileUpload(files[0]).then((response) =>
console.log('submit response', response)
)
}
event.preventDefault()
}
Next 中的 API 路由如下所示:
import formidable from 'formidable'
const fs = require('fs')
const { BlobServiceClient } = require('@azure/storage-blob')
if (process.env.NODE_ENV !== 'production') {
require('dotenv').config()
}
const AZURE_STORAGE_CONNECTION_STRING =
process.env.AZURE_STORAGE_CONNECTION_STRING
export const config = {
api: {
bodyParser: false,
},
}
const getBlobName = (originalName) => {
const identifier = Math.random().toString().replace(/0\./, '')
return `${identifier}-${originalName}`
}
export default async (req, res) => {
const form = new formidable.IncomingForm()
form.keepExtensions = true
form.uploadDir = './public/static/uploads'
form.parse(req, async (err, fields, files) => {
if (err) {
return
}
return res.json({ fields, files })
})
form.on('file', async (name, file) => {
const blobServiceClient = await BlobServiceClient.fromConnectionString(
AZURE_STORAGE_CONNECTION_STRING
)
const containerClient = await blobServiceClient.getContainerClient(
'images'
)
const buff = fs.readFileSync(file.path)
const data = buff.toString('base64')
const blobName = getBlobName(file.name)
const blockBlobClient = containerClient.getBlockBlobClient(blobName)
blockBlobClient.upload(data, data.length)
})
}
本地存储的图像已损坏,看起来就像调谐到死频道的电视。我显然没有正确编码它 - 但不确定它是我的 ContentType 还是字符串编码?
解决方案
我相信问题来了,因为您将数据转换为 base64 编码的字符串:
const data = buff.toString('base64')
考虑到您已经将上传的文件保存在服务器上的某个位置(这是通过formidable
包完成的),请尝试以下操作:
const blobName = getBlobName(file.name)
const blockBlobClient = containerClient.getBlockBlobClient(blobName)
blockBlobClient.uploadFile(file.path)
uploadFile()
方法参考:https ://docs.microsoft.com/en-gb/javascript/api/@azure/storage-blob/blockblobclient?view=azure-node-latest#uploadfile-string--blockblobparalleluploadoptions- 。
更新
请尝试此代码。我刚刚尝试了这段代码,并且能够成功上传文件。当我下载文件时,它没有损坏。
form.on('file', async (name, file) => {
const blobServiceClient = await BlobServiceClient.fromConnectionString(AZURE_STORAGE_CONNECTION_STRING);
const containerClient = await blobServiceClient.getContainerClient('images');
const blobName = file.name;
const contentType = file.type;
const filePath = file.path;
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
const uploadBlobResponse = await blockBlobClient.uploadFile(file.path);
});
更新#2
这是我使用的完整代码:
<form id="form1" method="post" action="/upload" enctype="multipart/form-data">
<input name="file" type="file" id="file1" accept="image/*"/>
<input type="button" id="button1" value="Upload" />
</form>
<script src="https://code.jquery.com/jquery-1.12.4.js" integrity="sha256-Qw82+bXyGq6MydymqBxNPYTaUXXq7c8v3CwiYwLLNXU=" crossorigin="anonymous"></script>
<script>
$(document).on('ready', function() {
});
$('#button1').on('click', function(e) {
data = new FormData();
console.log($('#file1')[0].files[0]);
data.append('file', $('#file1')[0].files[0]);
console.log(data);
$.ajax({
url: '/upload',
data: data,
processData: false,
contentType: false,
type: 'POST',
success: function ( data ) {
alert( data );
}
});
e.preventDefault();
e.stopPropagation();
});
</script>
var express = require('express'),
path = require('path'),
fs = require('fs'),
formidable = require('formidable');
const { BlobServiceClient } = require('@azure/storage-blob');
var app = express();
app.set('port', (process.env.PORT || 5000));
// Tell express to serve static files from the following directories
app.use(express.static('public'));
app.use('/uploads', express.static('uploads'));
app.listen(app.get('port'), function() {
console.log('Express started at port ' + app.get('port'));
});
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.post('/upload', function(req, res) {
const connectionString = 'DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=account-key;EndpointSuffix=core.windows.net;';
const container = 'container-name';
let form = new formidable.IncomingForm();
form.keepExtensions = true;
form.uploadDir = './public/static/uploads';
form.parse(req, async function (err, fields, files) {
});
form.on('file', async (name, file) => {
const blobServiceClient = await BlobServiceClient.fromConnectionString(connectionString);
const containerClient = await blobServiceClient.getContainerClient(container);
const blobName = file.name;
const contentType = file.type;
const filePath = file.path;
console.log(file);
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
const uploadBlobResponse = await blockBlobClient.uploadFile(file.path);
console.log(uploadBlobResponse);
});
});
推荐阅读
- python - pandas str 到 datetime 转换错误(60 分钟字段) ParserError: minute must be in 0..59: 2015-04-24 12:60:46
- html - 如何将隐藏输入的值传递给 Vue 实例的 data() 属性
- java - flink table api 日 年 月 提取
- python - 将正常的 for 循环结构转换为列表理解结构
- service - Android 10 中的 LocalService 和 LocalBinder 泄漏内存
- javascript - 嵌入谷歌幻灯片(iframe)我可以在网页中创建一个控制它的按钮吗?
- html - 盒子大小和媒体查询不起作用?
- flutter - 我正在尝试让用户登录,但我的代码仅在应用程序热重启时才有效
- flutter - 当我在 Stack(Positoned) 中使用 ListView 时出现问题
- python - 何时使用 int() 以及何时使用 var: int