使用Angular和Multer上传多个文件

时间:2019-05-13 10:45:56

标签: node.js angular express multer

我需要帮助来了解如何使用Angular 7处理multer(nodeJS)。 我尝试了一堆不同的情况,但似乎无法上传任何文件... 我的文件来自ReactiveForm:

<mat-tab
        label="Documents"
        formGroupName="docs">
          <mat-list>
              <mat-nav-list>
                <a mat-list-item
                (click)="fsPicker.click()">
                Upload financial statements
                </a><input type="file" #fsPicker (change)="onDocPicked($event, 'fs')">

                <a mat-list-item
                (click)="cdPicker.click()">
                Upload the constitutional documents
                </a><input type="file" #cdPicker (change)="onDocPicked($event, 'cd')">

                <a mat-list-item
                (click)="idPicker.click()">
                Upload the ID
                </a><input type="file" #idPicker (change)="onDocPicked($event, 'id')">

                <a mat-list-item
                (click)="adPicker.click()">
                Upload the bank account details
                </a><input type="file" #adPicker (change)="onDocPicked($event, 'ad')">

              </mat-nav-list>
          </mat-list>
        </mat-tab>

哪个由MimeValidator控制:

// INSIDE NGONINIT: 
    this.customerForm = new FormGroup({
          info: new FormGroup({
            name: new FormControl(null, {validators: Validators.required}),
            vat: new FormControl(null, {validators: Validators.required}),
          }),
          docs: new FormGroup({
            fs: new FormControl(null, {asyncValidators: mimeType}),
            cd: new FormControl(null, {asyncValidators: mimeType}),
            id: new FormControl(null, {asyncValidators: mimeType}),
            ad: new FormControl(null, {asyncValidators: mimeType})
          })
        });

// IN THE REST OF THE CLASS

  onDocPicked(event: Event, type: string) {
    const file = (event.target as HTMLInputElement).files[0];
    this.customerForm.get('docs').patchValue({
      [type]: file
    });
    this.customerForm.get('docs').get(type).updateValueAndValidity();
    this.customerForm.get('docs').get(type).markAsDirty();
    setTimeout(() => {
      if (!this.customerForm.get('docs').get(type).valid) {
      this.openAlert();
      this.customerForm.get('docs').patchValue({
          [type]: null
        });
      }
    }, 100);
  }

然后提交并发送到专用服务:

onSubmit() {
    if (!this.customerForm.valid) {
      return;
    }
    this.isLoading = true;
    if (!this.editMode) {

      this.customerService.addCustomer(this.customerForm.get('info').value, this.customerForm.get('docs').value);
      this.customerForm.reset();
    } else {
      const updatedCustomer: Customer = {
        id: this.id,
        name: this.customerForm.get('info').value.name,
        vat: this.customerForm.get('info').value.vat
      };
      this.customerService.updateCustomer(this.id, updatedCustomer);
    }
    this.router.navigate(['/customers']);
  }

在服务内部,已处理并发送到后端:

addCustomer(info, docsData) {
    const customerData = new FormData();
    customerData.append('name', info.name);
    customerData.append('vat', info.vat);
    customerData.append('docs', docsData);
    console.log(docsData);
    this.http.post<{message: string, customerId: string}>(
      'http://localhost:3000/api/customers',
      customerData
      )
      .subscribe((res) => {
        const customer: Customer = {
          id: res.customerId,
          name: info.name,
          vat: info.vat
        };
        this.customers.push(customer);
        this.customersUpdated.next([...this.customers]);
      });
  }

最后但并非最不重要的一点是快递和穆勒公司所接受和处理的:

  const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const isValid = MIME_TYPE_MAP[file.mimetype];
    let err = new Error('invalid mime type!');
    if (isValid) {
      err = null;
    }
    cb(err, 'backend/docs');
  },
  filename: (req, file, cb) => {
    const name = file.originalname.toLowerCase().split('').join('-');
    const ext = MIME_TYPE_MAP[file.mimetype];
    cb(null, name + '-' + Date.now() + '.' + ext);
  }
});

const upload = multer({storage: storage});

router.post('', upload.any(),
// .fields([
//   {name: 'fs'},
//   {name: 'cd'},
//   {name: 'id'},
//   {name: 'ad'},
//   ]),
  (req, res, next) => {
  const customer = new Customer({
    name: req.body.name,
    vat: req.body.vat,
  });
  customer.save().then(result => {
    res.status(201).json({
      message: 'Customer added successfully!',
      customerId: result.id
    });
  });
});

我认为问题出在我试图发送到服务器的对象上……但是我不确定如何正确处理。 即使调用multer的any命令,也不会保存任何内容。

这是stackblitz上整个项目的链接:

  

https://stackblitz.com/github/ardzii/test

1 个答案:

答案 0 :(得分:0)

我发送的数据类型错误。要更正(现在似乎可以正常工作),我必须在FormData中精确添加文件:

const customerData = new FormData();
    customerData.append('name', info.name);
    customerData.append('vat', info.vat);
    customerData.append('fs', docsData.fs as File, info.vat + 'fs');
    customerData.append('cd', docsData.cd as File, info.vat + 'cd');
    customerData.append('id', docsData.id as File, info.vat + 'id');
    customerData.append('ad', docsData.ad as File, info.vat + 'ad');

完成后,我可以通过调用multer轻松处理文件:

upload.
fields([
  {name: 'fs', maxCount: 1},
  {name: 'cd', maxCount: 1},
  {name: 'id', maxCount: 1},
  {name: 'ad', maxCount: 1},
  ]),

upload变量是带参数的multer实例(请参阅问题)。