如何将文件从 ReactJS 上传到 Express 端点
How to upload files from ReactJS to Express endpoint
在我目前正在处理的应用程序中,有几个文件格式通过superagent
提交到Express API端点。例如,图像数据是这样发布的:
handleSubmit: function(evt) {
var imageData = new FormData();
if ( this.state.image ) {
imageData.append('image', this.state.image);
AwsAPI.uploadImage(imageData, 'user', user.id).then(function(uploadedImage) {
console.log('image uploaded:', uploadedImage);
}).catch(function(err) {
this.setState({ error: err });
}.bind(this));
}
}
this.state.image
从文件输入中设置如下:
updateImage: function(evt) {
this.setState({
image: evt.target.files[0]
}, function() {
console.log('image:', this.state.image);
});
},
AWSAPI.uploadImage
看起来像这样:
uploadImage: function(imageData, type, id) {
var deferred = when.defer();
request.put(APIUtils.API_ROOT + 'upload/' + type + '/' + id)
.type('form')
.send(imageData)
.end(function(res) {
if ( !res.ok ) {
deferred.reject(res.text);
} else {
deferred.resolve(APIUtils.normalizeResponse(res));
}
});
return deferred.promise;
}
最后,文件接收端点如下所示:
exports.upload = function(req, res) {
req.pipe(req.busboy);
req.busboy.on('file', function(fieldname, file) {
console.log('file:', fieldname, file);
res.status(200).send('Got a file!');
});
};
目前,接收终结点的 on('file')
函数永远不会被调用,因此不会发生任何操作。以前,我用 multer 而不是 Busboy 尝试过类似的方法,但没有更多的成功(req.body
包含解码的图像文件,req.files
为空)。
我在这里错过了什么吗?将文件从 (ReactJS) Javascript 应用程序上传到 Express API 端点的最佳方法是什么?
我认为超级代理设置了错误的内容类型application/x-form-www-encoded
而不是multipart/form-data
您可以使用附加方法解决此问题,如下所示:
request.put(APIUtils.API_ROOT + 'upload/' + type + '/' + id)
.attach("image-file", this.state.image, this.state.image.name)
.end(function(res){
console.log(res);
});
有关附加方法的详细信息,请阅读此处的文档:http://visionmedia.github.io/superagent/#multipart-requests
由于这涉及 Nodejs 服务器脚本,我决定制作一个 GitHub 存储库而不是小提琴:https://github.com/furqanZafar/reactjs-image-upload
根据经验,使用 ajax 上传文件在使用 FormData
时有效,但是该文件必须是唯一的表单字段/数据。如果您尝试将其与其他数据(如用户名,密码或几乎任何数据)组合在一起,则无法正常工作。(可能有解决方法可以解决这个问题,但我不知道)
如果您需要发送用户名/密码,您应该将它们作为标头发送(如果可以的话)。
我采取的另一种方法是首先使用普通数据进行用户注册,然后在成功后,我将带有 FormData 的文件单独上传作为更新。
反应文件上传 iamges 组件:
class ImageUpload extends React.Component {
constructor(props) {
super(props);
this.state = {file: '',imagePreviewUrl: ''};
}
_handleSubmit(e) {
e.preventDefault();
// this.uploadImage()
// TODO: do something with -> this.state.file
console.log('handle uploading-', this.state.file); }
_handleImageChange(e) {
e.preventDefault();
let reader = new FileReader();
let file = e.target.files[0];
reader.onloadend = () => {
this.setState({
file: file,
imagePreviewUrl: reader.result
});
}
reader.readAsDataURL(file) }
// XHR/Ajax file upload uploadImage(imageFile) {
return new Promise((resolve, reject) => {
let imageFormData = new FormData();
imageFormData.append('imageFile', imageFile);
var xhr = new XMLHttpRequest();
xhr.open('post', '/upload', true);
xhr.onload = function () {
if (this.status == 200) {
resolve(this.response);
} else {
reject(this.statusText);
}
};
xhr.send(imageFormData);
}); }
render() {
let {imagePreviewUrl} = this.state;
let $imagePreview = null;
if (imagePreviewUrl) {
$imagePreview = (<img src={imagePreviewUrl} />);
} else {
$imagePreview = (<div className="previewText">Please select an Image for Preview</div>);
}
return (
<div className="previewComponent">
<form onSubmit={(e)=>this._handleSubmit(e)}>
<input className="fileInput" type="file" onChange={(e)=>this._handleImageChange(e)} />
<button className="submitButton" type="submit" onClick={(e)=>this._handleSubmit(e)}>Upload Image</button>
</form>
<div className="imgPreview">
{$imagePreview}
</div>
</div>
) } } React.render(<ImageUpload/>, document.getElementById("mainApp"));
服务器端映像保存并复制:
除了快递,你需要npm安装"多方"。此示例使用多方来解析表单数据并提取图像文件信息。然后"fs"将临时上传的图像复制到更永久的位置。
let multiparty = require('multiparty');
let fs = require('fs');
function saveImage(req, res) {
let form = new multiparty.Form();
form.parse(req, (err, fields, files) => {
let {path: tempPath, originalFilename} = files.imageFile[0];
let newPath = "./images/" + originalFilename;
fs.readFile(tempPath, (err, data) => {
// make copy of image to new location
fs.writeFile(newPath, data, (err) => {
// delete temp image
fs.unlink(tempPath, () => {
res.send("File uploaded to: " + newPath);
});
});
});
})
}
- 使用Express捕获参数
- 从模块内部访问Express装载路径
- 在Nodejs中Express输入DEBUG=app时权限被拒绝/bin
- 如何使用Node/Express显示有关特定错误的自定义html页面
- 发送json对象或使用express路由呈现视图
- renderReact/Rect Router+Node/Express.js的服务器端/同构渲染中未定义renderP
- 为什么不't Express呈现我的React应用程序
- Express服务器中语言子域的最佳实践
- 为什么不是'我的函数在解析云代码中工作吗?当我在Angular和Express中测试时,它是有效的
- Nodejs和express路由,如何处理客户端的承诺
- node.js和express中的异常处理
- 什么'在Express中路由时,应用程序级中间件和路由器级中间件之间的区别是什么
- 如何在不重新加载的情况下提交表单,并使用Node+Express将数据传递回同一页面
- Express.js:在用户发帖时获取用户的引荐来源网址
- 使用express.具有多个url和可选参数的Router()
- 使用connect vhost为多个express.js应用程序提供服务
- Express.js和multer:如何知道文件何时全部上传
- 将 https 添加到由 webpack 代理的 graphql express 端点
- 如何将文件从 ReactJS 上传到 Express 端点
- express.js HTTP方法与RESTapi端点