Загрузка нескольких файлов с Angular и Multer - PullRequest
0 голосов
/ 13 мая 2019

Мне нужна помощь, чтобы понять, как работать с multer (nodeJS) с Angular 7. Я пробовал кучу разных ситуаций, но не могу загрузить ни одного файла ... Мои файлы взяты из 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
    });
  });
});

Я полагаю, что проблема возникает из-за объекта, который я пытаюсь отправить на сервер ... Но я не уверен, как справиться с этим правильно. Даже при вызове команды any Малтера ничего не будет сохранено.

Вот ссылка на полный проект на stackblitz:

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

1 Ответ

0 голосов
/ 14 мая 2019

Я отправлял неверный тип данных.Чтобы исправить (и, похоже, это работает сейчас), мне нужно было указать в 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 переменная, являющаяся экземпляром объекта с параметрами (см. В вопросе).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...