【问题标题】:ngx-dropzone-wrapper + .NET Core Web APIngx-dropzone-wrapper + .NET Core Web API
【发布时间】:2018-10-01 08:40:09
【问题描述】:

由于某种原因,在将文件从 Angular 5 应用程序发送到我的 .NET Core Web API 时,我的 IFormFiles 集合始终为空。我猜我只是在某个地方寻找配置。有人看到这有什么问题吗?请注意,我使用的是 ngx-dropzone-wrapper (https://github.com/zefoy/ngx-dropzone-wrapper)。提前致谢!

home.component.html

<!-- Container -->
<div class="container">
    <form>
        <dropzone class="dropzone-container" [message]="'Click or drag groups of files to upload them to the Data Entry API'" (error)="uploadError($event)"
            (success)="uploadSuccess($event)" (queueComplete)="complete($event)" (sending)="sending($event)">
        </dropzone>
        <button (click)="processQueue()">Go</button>
    </form>
</div>
<!-- End Container -->

home.component.ts

import { Component, ViewEncapsulation, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import { DropzoneComponent, DropzoneDirective, DropzoneConfigInterface } from 'ngx-dropzone-wrapper';
import { DataEntryService } from '../../services/data-entry.service';
import Swal from 'sweetalert2'

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class HomeComponent implements AfterViewInit {

  // References to the dropzone component
  @ViewChild(DropzoneComponent) componentRef: DropzoneComponent;
  dropzone: any;

  // Flag to determine whether or not the 'Yes' button should be shown
  uploading: boolean = false;

  //** Constructor */
  constructor(private _dataEntryService: DataEntryService) { }

  /** Lifecycle hook that is called after a this component's view has been fully initialized */
  ngAfterViewInit() {

    // Get a reference ot the dropzone component
    this.dropzone = this.componentRef.directiveRef.dropzone();
  }

  /** 
   * Sends all queued files to our API (not the Data Entry API)
   * Triggered when the user clicks the 'Yes' button
   * @returns {void}
   * */
  processQueue(): void {

    console.log('Processing the queue');

    this.dropzone.processQueue();
  }

  /** 
   * Gets the xhr object and the formData objects as second and third parameters, so they can be modified or additional data can be added
   * Triggered by dropzone just before each file is sent
   * @param {any} args - The dropzone arguments
   * @returns {void}
   * */
  sending(args: any): void {

    console.log('Sending files');
    console.log(args);
  }

  /** 
   * Displays an error messages if one or more files were rejected by dropzone
   * Triggered by dropzone when an upload was either successfull or erroneous
   * @param {any} args - The dropzone arguments
   * @returns {void}
   * */
  complete(args: any): void {

    console.log('File upload comlpete');

    let accepted = this.dropzone.getAcceptedFiles();
    let rejected = this.dropzone.getRejectedFiles();
    let queued = this.dropzone.getQueuedFiles();
    let uploading = this.dropzone.getUploadingFiles();

    console.log('Accepted:  ' + accepted.length);
    console.log('Rejected:  ' + rejected.length);
    console.log('Queued:  ' + queued.length);
    console.log('Uploading:  ' + uploading.length);

    if (queued.length === 0 && uploading.length === 0) {

      if (rejected.length > 0) {

        Swal({
          type: 'error',
          title: 'Rejected Files',
          text: rejected.length + ' of the files that you uploaded were rejected. Please close this modal, correct your errors and try again.'
        });

        this.uploading = true;
      }
    }
  }

  /** 
   * For now, this just writes success messages to the console for debugging purposes
   * Triggered when a file has been uploaded successfully
   * @param {any} args - The dropzone arguments
   * @returns {void}
   * */
  uploadSuccess(args: any): void {

    console.log('Upload successful');

    if (args && args[0]) {
      console.log('File Uploaded:  ' + args[0].name);
    }
  }

  /** 
 * For now, this just writes error messages to the console for debugging purposes
 * Triggered when an upload error occurs
 * @param {any} args - The dropzone arguments
 * @returns {void}
 * */
  uploadError(args: any): void {

    console.error('Upload Error');

    if (args && args[1]) {
      console.error(args[1]);
    }
  }

}

配置

const DEFAULT_DROPZONE_CONFIG: DropzoneConfigInterface = {

  // Where we should send the files (Default: null)
  url: 'http://localhost:61143/api/xray',

  // Whether the queue will be processed automatically
  autoProcessQueue: false,

  // Optional oject to send additional headers to the server (Default: null)
  headers: null,

  // How many file uploads to process in parallel (Default: null)
  parallelUploads: 500,

  // Name of the file parameter that gets transferred (Default: 'file')
  paramName: 'file',

  // Maximum file size for the upload files in megabytes (Default: null)
  maxFilesize: 500,

  // Comma separated list of mime types or file extensions (Default: null)
  acceptedFiles: '.jpg, .dcm, .dicom',

  // Whether to send multiple files in one request (Default: null)
  uploadMultiple: true,

  // Whether thumbnails for images should be generated
  createImageThumbnails: false,

  // Whether to add a link to every file preview to remove or cancel (if already uploading) the file
  addRemoveLinks: true
};

.NET Core Web API 控制器

using System.Linq;
using Microsoft.AspNetCore.Mvc;
using DataEntry.Data;
using System;
using Microsoft.AspNetCore.Http;
using System.Collections.Generic;

namespace DataEntry.API.Controllers
{
    [Produces("application/json")]
    [Route("api/xray")]
    public class XRayController : Controller
    {
        private readonly DataEntryContext _db;

        public XRayController(DataEntryContext db)
        {
            _db = db;
        }

        // POST: api/xray
        [HttpPost]
        public IActionResult AddXRay(ICollection<IFormFile> files)
        {
            try
            {
                if (files == null || files.Count == 0)
                {
                    // Always 0 files here
                    throw new Exception("One or more JPG or DICOM file is required to upload X-rays.");
                }

                return Ok();
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }
    }
}

【问题讨论】:

  • 我知道这有点老了,但你能解决这个问题吗?遇到类似的事情。
  • 在我的情况下,它最终是我的 dropzone 发送了一个 Content-Type 标头(我自己的意外行为),这导致我的请求的 form.files 很奇怪,因此不能作为文件读取。
  • 我正在尝试从传递请求正文对象的服务调用 API。我在 API 中将对象作为请求正文传递,但无法获取文件信息。我想发送一个人的详细信息,如姓名等以及上传的个人资料图片。所以单独发送图片对我来说是行不通的,因为它会导致发送两个请求。你能帮我解决这个问题吗?

标签: .net angular asp.net-core-webapi dropzone


【解决方案1】:

您可以尝试将 ICollection 替换为 IFormFile[]

【讨论】:

  • 您好...我将 ICollection 更改为 IFormFile[]。另一种选择是您可以尝试使用 Request.Forms。
【解决方案2】:

您应该将 paramName 放入函数中(即 paramName: () => 'files')。原因可以在 dropzone.js 文件本身中找到:

// @options.paramName can be a function taking one parameter rather than a string.
// A parameter name for a file is obtained simply by calling this with an index number.
  _getParamName(n) {
    if (typeof this.options.paramName === "function") {
      return this.options.paramName(n);
    } else {
      return `${this.options.paramName}${this.options.uploadMultiple ? `[${n}]` : ""}`;
    }
  }

您想要实现的是防止将索引号(例如文件 [0])分配给 paramName,否则 paramName 与 .NET Core Web API 控制器中的不同。

这是没有记录的东西,我也不得不通过深入研究源代码自己找到它。

【讨论】:

    【解决方案3】:

    问题出在您的配置中。改变

    paramName: file // to 
    paramName: files
    

    【讨论】:

      猜你喜欢
      • 2018-05-08
      • 1970-01-01
      • 2018-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-23
      • 2018-03-26
      • 2018-11-06
      相关资源
      最近更新 更多