在 post 请求中发送带有文件的数据

Sending data with a file in a post request

我正在使用 Angular 11 将文件发送到我的节点/express.js 后端如何将数据与文件一起发送?

我有一个名为 sources 的架构,另一个名为 files 的 files 架构包含 sources 架构 id,以指示哪些文件属于哪些源。 在我的 angular 应用程序中,我循环遍历从源文档中获取的数据以显示它们,显示的每个源都有一个上传文件的选项。

我希望能够在我的 post 请求中将源 ID 与文件一起发送,以便将其存储在我的数据库中。

这是我使用的代码:

source.component.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;
  }
}

拖动-drop.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,
              });
            }
          }
        );
      });
  }

只需将附加字段添加到 formData,就像添加文件一样:

formData.append('sourceId', sourceId);

您似乎在服务器上使用了 Multer 中间件。根据文档,“req.body 将保留文本字段(如果有的话)”。