繁体   English   中英

从Angular2客户端到节点服务器的HTTP POST FormData

[英]HTTP POST FormData from Angular2 client to Node server

我有一个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不是函数

您的问题实际上是两个问题:

  1. 如何将文件从Angular表单发布到服务器?
  2. 如何处理(Node.js)服务器上的POST文件?

我不是Node.js专家,但是通过使用Node.js 强大模块来处理从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属性,也许就是问题所在。

笔记:

  • 我使用https://httpbin.org/post作为后端来调试POST请求(它返回请求中已收到的所有字段)。
  • 我的文件字段没有multiple选选项,但我认为代码可以正常工作。

就处理发布到Node.js服务器的文件而言,您的问题很可能是Content-Type 如果您使用诸如body-parser类的东西来处理nodejs服务器上的POST,则它将无法理解内容类型设置为multipart/form-data ,这就是FormData的用途。

注意这里的评论:

[body-parser]由于其复杂且通常较大的性质,因此无法处理多部分实体。 对于多部分实体,您可能对以下模块感兴趣:busboy和connect-busboy; 多方和连接多方; 强大; mul。

因此,换句话说,您必须使用其他模块来处理FormData发送的多部分主体。 我可以建议a 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');
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM