[英]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端點的最佳方法是什么?
我認為superAgent正在設置錯誤的內容類型的application/x-form-www-encoded
而不是multipart/form-data
你可以通過使用attach方法解決這個問題,如下所示:
request.put(APIUtils.API_ROOT + 'upload/' + type + '/' + id)
.attach("image-file", this.state.image, this.state.image.name)
.end(function(res){
console.log(res);
});
有關attach方法的更多信息,請閱讀此處的文檔: http : //visionmedia.github.io/superagent/#multipart-requests
因為這涉及到一個nodejs服務器腳本,所以我決定制作一個GitHub repo而不是一個小提琴: https : //github.com/furqanZafar/reactjs-image-upload
根據經驗,使用ajax上傳文件時使用FormData
,但文件必須是唯一的表單字段/數據。 如果您嘗試將其與其他數據(例如用戶名,密碼或幾乎任何內容)結合使用,則無效。 (可能有解決這個問題的工作,但我不知道)
如果您需要發送用戶名/密碼,您應該將其作為標題發送,如果可以的話。
我采取的另一種方法是首先使用普通數據進行用戶注冊,然后在成功時我將FormData作為更新單獨上傳。
react文件上傳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安裝'multiparty'。 此示例使用multiparty來解析表單數據並提取圖像文件信息。 然后'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);
});
});
});
})
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.