我有一个angular2客户端,我尝试使用FormData对象通过http将文件发送到我的NodeJS服务器。
upload.html
...
<input #fileinput type="file" [attr.multiple]="multiple ? true : null" (change)="uploadFile()" >
...
upload.component.ts
uploadFile() {
let files = this.fileinput.nativeElement.files;
if (files.length == 0) return;
this.formData = new FormData();
for (var i = 0; i < files.length; i++) {
console.log("Appended file: " + files[i].name + " File object:" + files[i]); // Output: Appended file: simple.txt File object:[object File]
this.formData.append(files[i].name, files[i]);
}
console.log("uploadFile formData: " + this.formData); // Output: uploadFile formData: [object FormData]
// this.formData.keys() (or any other function) results in TypeError: dataForm.keys is not a function
this.userService
.formDataUpload(this.formData)
.then((response: any) => {
console.log(response);
this.router.navigateByUrl('/');
});
}
user.service.ts
formDataUpload(formData: FormData): Promise<any> {
return this.http.post('/api/v0/formdataupload', formData)
.toPromise()
.then((response: any) => {
return response.json()
})
.catch(this.handleError);
}
server.js
app.post('/api/v0/formdataupload', function(req, res) {
console.log(req.body); // Output: {}
});
如何访问server.js中的FormData对象并获取上传的文件对象?另外,为什么我无法在upload.component.ts中使用任何FormData函数?所有函数抛出 TypeError:x不是函数。
答案 0 :(得分:2)
你的问题实际上是两个问题:
我没有Node.js专家,但使用Node.js nice tutorial模块快速搜索了formidable来处理来自Node.js的文件上传。
至于Angular部分,就文件上传而言,框架本身并没有多大帮助,所以这一切都归结为我们如何在普通JS中做到这一点?
您的代码似乎很好。这是一个稍微简化的工作版本(和Plunkr):
@Component({
selector: 'my-app',
template: `
<form [formGroup]="myForm">
<p><input type="file" formControlName="file1" (change)="uploadFile($event)"></p>
</form>
`
})
export class AppComponent {
myForm: ControlGroup;
constructor(fb: FormBuilder, private http: Http) {
this.myForm = fb.group({
file1: []
});
}
uploadFile(evt) {
const files = evt.target.files;
if (files.length > 0) {
let file;
let formData = new FormData();
for (let i = 0; i < files.length; i++) {
file = files[i];
formData.append('userfile', file, file.name);
}
this.http.post('https://httpbin.org/post', formData)
.map(resp => resp.json())
.subscribe(data => console.log('response', data));
}
}
}
与代码的显着区别在于我访问输入文件元素的files
属性的方式。在您的代码中,在模板中编写<input #fileinput>
并不会自动在您的组件中创建fileinput
属性,这可能就是问题所在。
注意:
multiple
选项,但我认为代码可以正常工作。答案 1 :(得分:0)
在处理发布到Node.js服务器的文件方面,您的问题可能是Content-Type
之一。如果您使用body-parser
之类的东西来处理nodejs服务器上的POST,那么它将无法理解内容类型设置为multipart/form-data
的表单,这是FormData处理的内容。
请注意评论here:
[body-parser]由于其复杂且通常较大的性质而无法处理多部分主体。对于多部分机构,您可能对以下模块感兴趣:busboy和connect-busboy;多方和连接多方;强大; multer。
换句话说,您必须使用不同的模块来处理FormData发送的多部分主体。我可以推荐formidable
,在这种情况下,您的服务器代码应该类似于:
const formidable = require('formidable')
exports.createPost = (req, res, next) => {
var form = new formidable.IncomingForm();
form.parse(req, (err, fields, files) => {
console.log(fields)
res.send('NOT IMPLEMENTED: pollsController createPost');
}
}