首页 > 解决方案 > 我想使用 http 发布请求将带有图像的表单数据从 Angular 上传到 Node.js?

问题描述

html:在这些模板中,我要求提供产品信息和图像并存储它。

      <input type="hidden" formControlName="_id">

      <input type="file" formControlName="ProductImage" #ProductImage>

      <mat-form-field>           
        <input formControlName="productName" matInput placeholder="Product Name" #productName>
        <mat-hint align="end">{{ productName.value.length }}/50</mat-hint>

        <mat-error *ngIf="productForm.get('productName').hasError('required') && productForm.get('productName').touched; else patternproductName;">This is required</mat-error>
        <ng-template #patternproductName>
          <mat-error *ngIf="productForm.get('productName').hasError('pattern'); else lengthproductName;">Invalid characters</mat-error>  
        </ng-template>
        <ng-template #lengthproductName>
          <mat-error *ngIf="productForm.get('productName').hasError('minlength') || productForm.get('productName').hasError('maxlength');">Must be 1-50 characters</mat-error>
        </ng-template>
      </mat-form-field>

      <mat-form-field> 
        <mat-select formControlName="supplierId" matInput placeholder="Supplier" #supplierId>
          <mat-option *ngFor="let a of supplierArray" value="{{ a._id }}">{{ a.supplierName }}</mat-option>
        </mat-select>

        <mat-error *ngIf="productForm.get('supplierId').hasError('required') && productForm.get('supplierId').touched; else patternsupplierId;">This is required</mat-error>
        <ng-template #patternsupplierId>
          <mat-error *ngIf="productForm.get('supplierId').hasError('pattern'); else lengthsupplierId;">Invalid characters</mat-error>  
        </ng-template>
        <ng-template #lengthsupplierId>
          <mat-error *ngIf="productForm.get('supplierId').hasError('minlength') || productForm.get('supplierId').hasError('maxlength');">Must be 1-24 characters</mat-error>
        </ng-template>
      </mat-form-field>   

      <mat-form-field> 
        <mat-select formControlName="brandId" matInput placeholder="Brand" #brandId>
          <mat-option *ngFor="let a of brandArray" value="{{ a._id }}">{{ a.brandName }}</mat-option>
        </mat-select>
        <mat-error *ngIf="productForm.get('brandId').hasError('required') && productForm.get('brandId').touched; else patternbrandId;">This is required</mat-error>
        <ng-template #patternbrandId>
          <mat-error *ngIf="productForm.get('brandId').hasError('pattern'); else lengthbrandId;">Invalid characters</mat-error>  
        </ng-template>
        <ng-template #lengthbrandId>
          <mat-error *ngIf="productForm.get('brandId').hasError('minlength') || productForm.get('brandId').hasError('maxlength');">Must be 1-24 characters</mat-error>
        </ng-template>
      </mat-form-field>  

      <mat-form-field> 
        <mat-select formControlName="categoryId" matInput placeholder="Category" #categoryId>
          <mat-option *ngFor="let a of categoryArray" value="{{ a._id }}">{{ a.categoryName }}</mat-option>
        </mat-select>
        <mat-error *ngIf="productForm.get('categoryId').hasError('required') && productForm.get('categoryId').touched; else patterncategoryId;">This is required</mat-error>
        <ng-template #patterncategoryId>
          <mat-error *ngIf="productForm.get('categoryId').hasError('pattern'); else lengthcategoryId;">Invalid characters</mat-error>  
        </ng-template>
        <ng-template #lengthcategoryId>
          <mat-error *ngIf="productForm.get('categoryId').hasError('minlength') || productForm.get('categoryId').hasError('maxlength');">Must be 1-20 characters</mat-error>
        </ng-template>
      </mat-form-field>  

      <mat-form-field>           
        <input formControlName="productPrice" matInput placeholder="Price" #productPrice>
        <mat-hint align="end">{{ productPrice.value.length }}/5</mat-hint>

        <mat-error *ngIf="productForm.get('productPrice').hasError('required') && productForm.get('productPrice').touched; else patternproductPrice;">This is required</mat-error>
        <ng-template #patternproductPrice>
          <mat-error *ngIf="productForm.get('productPrice').hasError('pattern'); else lengthproductPrice;">Invalid characters</mat-error>  
        </ng-template>
        <ng-template #lengthproductPrice>
          <mat-error *ngIf="productForm.get('productPrice').hasError('min') || productForm.get('productPrice').hasError('max');">Must be between 1-99999</mat-error>
        </ng-template>
      </mat-form-field>


      <mat-form-field>           
        <input formControlName="productQuantity" matInput placeholder="Quantity" #productQuantity>
        <mat-hint align="end">{{ productQuantity.value.length }}/5</mat-hint>

        <mat-error *ngIf="productForm.get('productQuantity').hasError('required') && productForm.get('productQuantity').touched; else patternproductQuantity;">This is required</mat-error>
        <ng-template #patternproductQuantity>
          <mat-error *ngIf="productForm.get('productQuantity').hasError('pattern'); else lengthproductQuantity;">Invalid characters</mat-error>  
        </ng-template>
        <ng-template #lengthproductQuantity>
          <mat-error *ngIf="productForm.get('productQuantity').hasError('min') || productForm.get('productQuantity').hasError('max');">Must be between 1-99999</mat-error>
        </ng-template>
      </mat-form-field>

      <mat-form-field>           
        <input formControlName="productMin" matInput placeholder="Minimum" #productMin>
        <mat-hint align="end">{{ productMin.value.length }}/5</mat-hint>

        <mat-error *ngIf="productForm.get('productMin').hasError('required') && productForm.get('productMin').touched; else patternproductMin;">This is required</mat-error>
        <ng-template #patternproductMin>
          <mat-error *ngIf="productForm.get('productMin').hasError('pattern'); else lengthproductMin;">Invalid characters</mat-error>  
        </ng-template>
        <ng-template #lengthproductMin>
          <mat-error *ngIf="productForm.get('productMin').hasError('min') || productForm.get('productMin').hasError('max');">Must be between 0-99999</mat-error>
        </ng-template>
      </mat-form-field>


      <button mat-raised-button class="pull-right" [mat-dialog-close]="true">Cancel</button>
      <button type="submit" mat-raised-button color="primary" class="pull-right" *ngIf="!formSelector" [disabled]="!productForm.valid" (click)="openSnackBar(productNotification)">Create</button>
      <button type="submit" mat-raised-button color="primary" class="pull-right" *ngIf="formSelector" [disabled]="!productForm.valid" (click)="openSnackBar(productNotification)">Update</button>

    </form>
  </ng-template>  

这是当用户完成表单并单击提交按钮时执行的打字稿文件。我想获取图像作为 wend 并将其加入 productSchema 并通过使用服务
.ts 将其发送到节点服务器:

productSubmit(form){ 
        const Image = this.Product_Image.nativeElement;
        if(Image.files && Image.files[0]){
          this.ProductImageFile = Image.files[0];
        }
        const ImageFile: File = this.ProductImageFile;

        let productSchema: productSchema = {
          '_id': form.value._id,
          'productImage': ImageFile, 
          'productName': form.value.productName,
          'supplierId': form.value.supplierId,
          'brandId': form.value.brandId,
          'categoryId': form.value.categoryId,
          'productPrice': form.value.productPrice,
          'productQuantity': form.value.productQuantity,
          'productMin': form.value.productMin
        }; 
        console.log(productSchema);
        if(!this.formSelector){ //create method
          this.productService.productCreate(productSchema).subscribe(result =>{
            this.notif = "created";
            this.productForm.reset();
            this.productSelect();
          });
        }
      }

架构:这是我要在所有字段中实现的架构

const mongoose = require('mongoose');
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
const productSchema = mongoose.Schema({
    ProductImage: {
        type: String,
        required: true
    },
    productName: {
        type: String,
        required: true,
        minlength: 1, 
        maxlength: 50
    },
    supplierId: {
        type: ObjectId,
        required: true,
        minlength: 24,
        maxlength: 24
    },
    brandId: {
        type: ObjectId,
        required: true,
        minlength: 24,
        maxlength: 24
    },
    categoryId: {
        type: ObjectId,
        required: true,
        minlength: 24,
        maxlength: 24
    },
    productPrice: {
        type: Number,
        required: true,
        minlength: 1,
        maxlength: 5
    },
    productQuantity: {
        type: Number,
        required: true,
        minlength: 1,
        maxlength: 5
    },
    productMin: {
        type: Number,
        required: true,
        minlength: 1,
        maxlength: 5
    },
    productExist: {
        type: Boolean,
        required: true,
        default: true
    },
    productTimeStamp: {
        type: Date,
        required: true,
        default: Date.now
    }

});

module.exports = mongoose.model('productSchema', productSchema);  

这是将表单数据发送到 nodejs服务的
服务:

  productCreate(val){
    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    return this.http.post('http://localhost:3000/api/productCreate', val, { headers: headers }).pipe(map(res => res.json()));
  }

节点.js

    var store = multer.diskStorage({
        destination: (req, file, cb) => {
            cb(null, './uploads');
        },
        filename: (re, file, cb) => {
            cb(null, Date.now() + '.' + file.originalname);
            console.log(file);
        }
    });

    //start saving picture
    var upload = multer({storage: store}).single('file');
    router.post('/upload', (req, res, next) => {
        upload(req, res, (err) => {
            if(err) return res.status(501).json({ error: err });
            return res.json({ originalname: req.file.originalname, uploadname: req.file.filename });
        });
    });
    //end saving picture

    router.post('/productCreate', upload, (req, res, next) =>{
        console.log(req);
        let newproductSchema = new productSchema({
            productImage: req.file,
            productName: req.body.productName,
            supplierId: req.body.supplierId,
            brandId: req.body.brandId,
            categoryId: req.body.categoryId,
            productPrice: req.body.productPrice,
            productQuantity: req.body.productQuantity,
            productMax: req.body.productMax,
            productMin: req.body.productMin
        });
        console.log(newproductSchema);
        newproductSchema.save((err, newproductSchema) =>{
            if(err) res.json(err);
            else res.json({msg: 'Item added successful'});
        });
    });

我想创建一个将产品信息和图像也保存到 mongodb 的系统。我想将图像的路径存储在数据库中。我对如何将文件从角度发送到节点感到困惑。你能帮我解决这些问题吗?谢谢你。我想用一张图片上传表单数据。但我做不到。我该如何解决这些问题?

标签: node.jsangulartypescriptangular-materialmulter

解决方案


您可以将图像放入画布,然后从画布中检索 blob 或 dataUrl,将其作为属性附加到您正在使用的服务器的 get/post 请求中,并将图像作为字节块直接存储在 MongoDB 中或一个 base64 编码的字符串。要检索它,您只需将图像的 src 设置为存储在 MonoDB 中的 dataUrl。

示例: https ://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL


推荐阅读