Exemplo n.º 1
0
        private static void PrepForReExecute(HttpContext context, UploadErrorsModel uploadErrorsModel)
        {
            // Clear request
            context.Request.Method = "POST";
            context.Request.Body   = Stream.Null;

            var query = new Dictionary <string, StringValues> {
                [nameof(uploadErrorsModel.Errors)] = uploadErrorsModel.Errors
            };

            context.Request.QueryString = QueryString.Create(query);
            context.Request.ContentType = "text/plain";

            // Set route data
            var routeData = new {
                controller = "Upload",
                action     = "Frame",
                id         = context.GetRouteValue("fileIdentifier")
            };

            foreach (IRouter router in context.GetRouteData().Routers.Reverse())
            {
                VirtualPathContext virtualPathContext = new VirtualPathContext(context, new RouteValueDictionary(), new RouteValueDictionary(routeData));
                VirtualPathData    data = router.GetVirtualPath(virtualPathContext);

                if (data != null)
                {
                    context.Request.Path = new PathString(data.VirtualPath);

                    return;
                }
            }
        }
Exemplo n.º 2
0
    private static void PrepForReExecute(HttpContext context, UploadErrorsModel uploadErrorsModel)
    {
        // Clear request
        context.Request.Method = "POST";
        context.Request.Body   = Stream.Null;

        if (uploadErrorsModel.Errors?.Length > 0)
        {
            Dictionary <string, StringValues> query = new Dictionary <string, StringValues> {
                [nameof(uploadErrorsModel.Errors)] = uploadErrorsModel.Errors
            };
            context.Request.QueryString = QueryString.Create(query);
        }
        else
        {
            context.Request.QueryString = new QueryString();
        }

        // Reset the request in its most basic form
        context.Request.ContentType = "text/plain";
        context.Request.PathBase    = "/";
        context.Request.Path        = "/";

        // Set endpoint and associated routing data
        const string continuationEndpoint         = "AfterUploadCompletionFrame";
        IEndpointAddressScheme <string> svc       = context.RequestServices.GetRequiredService <IEndpointAddressScheme <string> >();
        IEnumerable <Endpoint>          endpoints = svc.FindEndpoints(continuationEndpoint);

        bool hasSetEndpoint = false;

        foreach (Endpoint endpoint in endpoints)
        {
            if (hasSetEndpoint)
            {
                throw new InvalidOperationException($"Multiple endpoints {continuationEndpoint}");
            }

            // Prepare routing values MVC uses for view lookups
            ControllerActionDescriptor?actionDescriptor = endpoint.Metadata.GetMetadata <ControllerActionDescriptor>();
            if (actionDescriptor != null)
            {
                RouteData routeData = context.GetRouteData();

                foreach (KeyValuePair <string, string?> routeValue in actionDescriptor.RouteValues)
                {
                    routeData.Values[routeValue.Key] = routeValue.Value;
                }
            }

            // Set to endpoint to use later
            context.SetEndpoint(endpoint);
            hasSetEndpoint = true;
        }

        if (!hasSetEndpoint)
        {
            throw new InvalidOperationException($"Unable to find continuation endpoint {continuationEndpoint}");
        }
    }
Exemplo n.º 3
0
    public IActionResult Frame(FileIdentifier fileIdentifier, UploadErrorsModel model)
    {
        if (model?.Errors != null)
        {
            foreach (string modelError in model.Errors)
            {
                this.ModelState.AddModelError(modelError, modelError);
            }
        }

        if (!this.ModelState.IsValid)
        {
            return(this.View("FrameError", model));
        }

        return(this.View("FrameComplete", fileIdentifier));
    }
Exemplo n.º 4
0
    public async Task ExecuteAsync(HttpContext context)
    {
        FileIdentifier identifier = FileIdentifier.FromString(context.GetRouteValue("fileIdentifier")?.ToString() ?? throw new InvalidOperationException("No ID"));

        this._logger.LogInformation(LogEvents.NewUpload, "New upload of file with id {0}", identifier);

        // We have already the ID, so we can set some progress
        UploadProgress progress = new UploadProgress {
            Current   = 0,
            StartTime = DateTime.UtcNow,
            Total     = context.Request.ContentLength ?? -1
        };

        this._uploadProgressManager.SetProgress(identifier, progress);

        // Initialize reading request
        MediaTypeHeaderValue contentType = GetContentType(context);
        string boundary = GetBoundary(contentType);

        MultipartReader reader = new MultipartReader(boundary, context.Request.Body);

        reader.BodyLengthLimit = (long?)this._fileStoreOptions.Value?.MaximumFileSize.Megabytes().Bytes;

        // Delegate actual request parsing
        // ... after the request "completes" we re-execute to send the final response to the browser
        try {
            await using (context.RequestAborted.Register(context.Abort)) {
                await this._uploadManager.StoreAsync(identifier, reader, context.RequestAborted);
            }

            PrepForReExecute(context, new UploadErrorsModel());
        }
        catch (UploadCryptoArgumentOrderException) {
            PrepForReExecute(context, UploadErrorsModel.CreateFromMessage("Invalid order of cryptographic parameters: file was uploaded before password."));
        }
        catch (Exception ex) {
            UploadErrorsModel errors = UploadErrorsModel.CreateFromMessage(ex.Message);

            this._logger.LogError(LogEvents.UploadFailed, "Detected failed upload - passing error to child handler: {0}", ex);

            PrepForReExecute(context, errors);
        }

        await ReExecuteAsync(context);
    }