Отправка данных с файлом в почтовом запросе

#javascript #node.js #angular #express #mean-stack

Вопрос:

Я использую Angular 11 для отправки файла на свой узел / express.js серверная часть как мне отправить данные вместе с файлом?

У меня есть схема, называемая источниками, и другая, называемая файлами.Схема файлов содержит идентификатор схемы источников, чтобы указать, какие файлы принадлежат каким источникам. В моем приложении angular я перебираю данные, извлеченные из документов источника, чтобы отобразить их, каждый отображаемый источник имеет возможность загрузить файл.

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

Вот код, который я использовал :

источник.компонент.ts

 @Component({
  selector: 'app-source',
  templateUrl: './source.component.html',
  styleUrls: ['./source.component.scss'],
})
export class SourceComponent implements OnInit {
  showModal: boolean = false;
  faUpload = faUpload;
  @Input() datasource: {
    _id: string;
    name: string;
    description: string;
    imagePath: string;
  };
  @Input() searchPlaceHolder1: string;
  @Input() searchPlaceHolder2: string;
  
  isModalActive: boolean = false;
  @Output() messageEvent = new EventEmitter<string>();
  select: string = 'not selected yet';
  searchText: string = '';
  fileArr = [];
  sheetArr = [];
  fileObj = [];
  form: FormGroup;
  msg: string;
  progress: number = 0;
  isButtonVisible: boolean = true;
  constructor(
    public fb: FormBuilder,
    private sanitizer: DomSanitizer,
    public dragdropService: DragdropService
  ) {
    this.form = this.fb.group({
      txt: [null],
    });
  }

  ngOnInit(): void {}
  onSelect() {
    this.select = 'selected';
  }
  sendMessage() {
    this.messageEvent.emit(this.datasource.name);
  }

  upload(e) {
    const fileListAsArray = Array.from(e);
    fileListAsArray.forEach((item, i) => {
      const file = e as HTMLInputElement;
      const url = URL.createObjectURL(file[i]);
      this.sheetArr.push(url);
      this.fileArr.push({ item, url: url });
    });

    this.fileArr.forEach((item) => {
      this.fileObj.push(item.item);
    });

    // Set files form control
    this.form.patchValue({
      txt: this.fileObj,
    });

    this.form.get('txt').updateValueAndValidity();

    // Upload to server
    this.dragdropService
      .addFiles(this.form.value.txt)
      .subscribe((event: HttpEvent<any>) => {
        switch (event.type) {
          case HttpEventType.Sent:
            console.log('Request has been made!');
            break;
          case HttpEventType.ResponseHeader:
            console.log('Response header has been received!');
            break;
          case HttpEventType.UploadProgress:
            this.progress = Math.round((event.loaded / event.total) * 100);
            console.log(`Uploaded! ${this.progress}%`);
            break;
          case HttpEventType.Response:
            console.log('File uploaded successfully!', event.body);
            setTimeout(() => {
              this.progress = 0;
              this.fileArr = [];
              this.fileObj = [];
              this.msg = 'File uploaded successfully!';
            }, 3000);
        }
      });
  }

  // Clean Url
  sanitize(url: string) {
    return this.sanitizer.bypassSecurityTrustUrl(url);
  }
  loading = { 1: false, 2: false, 3: false, 4: false };

  doSomething(i: number) {
    console.log('Clicked');

    this.loading[i] = true;
    setTimeout(() => {
      this.loading[i] = false;
    }, 2000);
  }

  selectItem() {
    this.showModal = true;
  }
}

 

перетащите.service.ts

 @Injectable({
  providedIn: 'root',
})
export class DragdropService {
  constructor(private http: HttpClient) {}

  addFiles(sheets: File) {
    var arr = [];
    var formData = new FormData();
    arr.push(sheets);

    arr[0].forEach((item, i) => {
      formData.append('txt', arr[0][i]);
    });

    return this.http
      .post('http://localhost:4000/upload-file', formData, {
        reportProgress: true,
        observe: 'events',
      })
      .pipe(catchError(this.errorMgmt));
  }

  errorMgmt(error: HttpErrorResponse) {
    let errorMessage = '';
    if (error.error instanceof ErrorEvent) {
      // Get client-side error
      errorMessage = error.error.message;
    } else {
      // Get server-side error
      errorMessage = `Error Code: ${error.status}nMessage: ${error.message}`;
    }
    console.log(errorMessage);
    return throwError(errorMessage);
  }
}
 

Что касается внутреннего кода :

 app.post("/upload-file", uploads.single("txt"), (req, res) => {
  //convert csvfile to jsonArray
  if (
    req.file.mimetype === "application/vnd.ms-excel" ||
    req.file.mimetype === "application/csv" ||
    req.file.mimetype === "text / csv"
  ) {
    const fileName = req.file.originalname;

    csv({
      delimiter: ";",
    })
      .fromFile(req.file.path)
      .then((jsonObj) => {
        //insertmany is used to save bulk data in database.
        //saving the data in collection(table)
        //finding the document using fileName and setting csvData as the jsonObj
        sheetModel.findOneAndUpdate(
          { fileName: fileName },
          { $set: { csvData: jsonObj } },
          { upsert: true }, // if name does not exist insert
          (err, csvData) => {
            if (err) {
              res.status(400).json({
                message: "Something went wrong!",
              });
            } else {
              res.status(200).json({
                message: "File Uploaded Successfully!",
                result: csvData,
              });
            }
          }
        );
      });
  }
 

Ответ №1:

Просто добавьте дополнительные поля formData так же, как вы добавляете файлы:

 formData.append('sourceId', sourceId);
 

Похоже, что вы используете промежуточное программное обеспечение Multer на сервере. Согласно документации, « req.body будут содержаться текстовые поля, если таковые имелись».