【问题标题】:File Upload with Relay and graphql-dotnet使用 Relay 和 graphql-dotnet 上传文件
【发布时间】:2017-03-25 15:15:44
【问题描述】:

我正在尝试在中继中构建一个包含文件的突变。只要我实现这里引用的getFiles() 方法:https://facebook.github.io/relay/docs/api-reference-relay-mutation.html#getfiles

中继发送多部分请求,导致 ASP.NET Core MVC 出现 415 错误。

我正在寻找一个工作示例,类似于带有graphql-dotnet library 的“How would you do file uploads in a React-Relay app?”。

【问题讨论】:

    标签: asp.net asp.net-mvc graphql relayjs graphql-dotnet


    【解决方案1】:

    GraphQL 端点不接受多部分表单 mimetype,因为它不是 JSON。一旦我通过 RootObject 和突变中可用的上下文将它们放入 graphql-dotnet 中,我就能够使用这些文件。让我失望的是 MVC。

    所以我写了一个简单的过滤器:

    public class RelayResourceFilter : IResourceFilter
    {
        private readonly string jsonMediaType = "application/json";
    
        public void OnResourceExecuted(ResourceExecutedContext context)
        {
        }
    
        public void OnResourceExecuting(ResourceExecutingContext context)
        {
    
    
            if (!string.Equals(MediaTypeHeaderValue.Parse(context.HttpContext.Request.ContentType).MediaType,
                this.jsonMediaType, StringComparison.OrdinalIgnoreCase))
            {
                var encoder = JavaScriptEncoder.Create();
                var variables = encoder.Encode(context.HttpContext.Request.Form["variables"]);
                var query = encoder.Encode(context.HttpContext.Request.Form["query"]);
                var body = $"{{\"query\":\"{query}\", \"variables\":\"{variables}\"}}";
    
                byte[] requestData = Encoding.UTF8.GetBytes(body);
                context.HttpContext.Request.Body = new MemoryStream(requestData);
                context.HttpContext.Request.ContentType = this.jsonMediaType;
            }
        }
    }
    

    注册了:

    services.AddScoped<RelayResourceFilter>();
    

    然后像这样在Controller中应用它:

    [ServiceFilter(typeof(RelayResourceFilter))]
        public async Task<ExecutionResult> Post([FromBody]GraphQLQuery query, bool? useErrorCode)
    {
    var files = this.Request.HasFormContentType ? this.Request.Form.Files : null;
    // ... assignment to Root Object
    }
    

    【讨论】:

      【解决方案2】:

      您是否只是不知道如何访问服务器上解析器中的文件?您可以将文件作为rootObjectuserContext 传递。

      // GraphQLController
      var files = Request.Form.Files;
      var userContext = files;
      
      var result = await executer.ExecuteAsync(
          schema,
          rootObject,
          query,
          operationName,
          inputs,
          userContext).ConfigureAwait(false);
      
      // Mutation type
      Field<StringGraphType>(
        "uploadFile",
        arguments: new QueryArguments(new QueryArgument<NonNullGraphType<StringGraphType>> {Name = "fileName"}),
        resolve: context =>
        {
            var userContext = context.UserContext.As<IFormFileCollection>();
      
            // process files
      
            // return data
            return "success";
        });
      

      【讨论】:

      • 感谢乔的回复。实际上,我最终为 GraphQL 端点编写了一个小的 ResourceFilter:
      • 我如何阅读他的查询?一般来说,我是这样阅读的var request = JsonConvert.DeserializeObject&lt;GraphQLQueryModel&gt;(body);。然后request 是包含查询的对象。如果我上传的文件内容不是application/json.
      • @kat1330 我会看看接受的答案。您需要检查媒体类型。另见github.com/graphql-dotnet/relay/blob/master/src/GraphQL.Relay/…
      • @JoeMcBride 谢谢。我更喜欢使用的是中间件。你知道哪种类型最适合突变QueryArgument进行文件上传吗?
      • @kat1330 我不确定我是否完全理解你的问题(也许在 GraphQL .NET 项目上添加一个问题并提供更多信息?) - 但我想你是在问你如何将文件作为查询传递论据。简短的回答是你不能。您必须通过用户上下文访问它们。
      猜你喜欢
      • 2018-06-27
      • 1970-01-01
      • 2018-02-12
      • 2016-02-10
      • 2015-11-27
      • 2021-06-24
      • 2019-10-13
      • 1970-01-01
      • 2016-07-21
      相关资源
      最近更新 更多