Загрузка файла ядра Asp.net с помощью Graphql-dotnet - PullRequest
0 голосов
/ 04 июня 2018

Я пытаюсь загрузить файл изображения с помощью graphql-dotnet , но это никогда не удается.

Я беру файловый объект в моем GraphQLController:

var files = this.Request.Form.Files;

var executionOptions = new ExecutionOptions 
{
    Schema = _schema,
    Query = queryToExecute,
    Inputs = inputs,
    UserContext = files,
    OperationName = query.OperationName
};

И вот моя Мутация:

Field<UserGraphType>(
    "uploadUserAvatar",
    Description="Kullanıcı resmi yükleme.",
    arguments: new QueryArguments(
        new QueryArgument<NonNullGraphType<IntGraphType>> { Name = "Id", Description = "Identity Alanı" }
    ),
    resolve: context => {
        var file = context.UserContext.As<IFormCollection>();
        var model = userService.UploadAvatar(context.GetArgument<int>("Id"),file);
        return true;
    }
);

Я думаю, что он принимает единственный JSON.Он не принимает запрос как тип файла.

Также я использую React & apollo-client на стороне клиента.В консоли есть ошибка:

Не удалось загрузить http://localhost:5000/graphql: Нет заголовка 'Access-Control-Allow-Origin' в запрашиваемом ресурсе.Происхождение 'http://localhost:8080' поэтому не допускается.Ответ имеет HTTP-код состояния 500. Если непрозрачный ответ удовлетворяет вашим потребностям, установите режим запроса «no-cors», чтобы получить ресурс с отключенным CORS.

Я пытаюсь отправить запроскак это:

const { selectedFile,id } = this.state

this.props.uploadAvatar({
    variables: {id},
    file:selectedFile
}).then(result => {
    console.log(result);
});

Что я могу сделать, чтобы достичь этого?

1 Ответ

0 голосов
/ 05 июня 2018

Не удалось загрузить http://localhost:5000/graphql: Нет заголовка «Access-Control-Allow-Origin» на запрошенном ресурсе.Следовательно, Origin 'http://localhost:8080' не разрешен доступ.

Эта ошибка означает, что вам необходимо включить CORS.

См. Следующие документы: https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-2.1

По сути, вам нужны эти две вещи:

services.AddCors();

app.UseCors(builder =>
   builder.WithOrigins("http://example.com"));

Я бы также предложил взглянуть на эту вспомогательную функцию Deserializer в проекте GraphQL.Relay.Это помогает вашему серверу обрабатывать запрос multipart/form-data.Затем вы можете использовать проанализированные данные запроса и файлы и передать их в DocumentExecutor.

https://github.com/graphql-dotnet/relay/blob/master/src/GraphQL.Relay/Http/Deserializer.cs

public static class Deserializer
{
    public static async Task<RelayRequest> Deserialize(Stream body, string contentType)
    {
        RelayRequest queries;

        switch (contentType)
        {
            case "multipart/form-data":
                queries = DeserializeFormData(body);
                break;
            case "application/json":
                var stream = new StreamReader(body);
                queries = DeserializeJson(await stream.ReadToEndAsync());
                break;
            default:
                throw new ArgumentOutOfRangeException($"Unknown media type: {contentType}. Cannot deserialize the Http request");
        }

        return queries;
    }


    private static RelayRequest DeserializeJson(string stringContent)
    {
        if (stringContent[0] == '[')
            return new RelayRequest(
                JsonConvert.DeserializeObject<RelayQuery[]>(stringContent),
                isBatched: true
            );

        if (stringContent[0] == '{')
            return new RelayRequest() {
                JsonConvert.DeserializeObject<RelayQuery>(stringContent)
            };

        throw new Exception("Unrecognized request json. GraphQL queries requests should be a single object, or an array of objects");
    }

    private static RelayRequest DeserializeFormData(Stream body)
    {
        var form = new MultipartFormDataParser(body);

        var req = new RelayRequest()
        {
            Files = form.Files.Select(f => new HttpFile {
                ContentDisposition = f.ContentDisposition,
                ContentType = f.ContentType,
                Data = f.Data,
                FileName = f.FileName,
                Name = f.Name
            })
        };

        req.Add(new RelayQuery {
            Query = form.Parameters.Find(p => p.Name == "query").Data,
            Variables = form.Parameters.Find(p => p.Name == "variables").Data.ToInputs(),
        });

        return req;
    }
}
...