Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
641 views
in Technique[技术] by (71.8m points)

node.js - 502 error upload csv file to web api

I have an Angular5 user interface with a file upload function. The user clicks a button and selects a file and the file is sent to the web api (asp.NET Core) method for processing.

This works fine with smaller files, but with larger files the request times out with a 502 error.

I can see the request always timesout at 120 seconds. (NOTE: I am hosting via node in development and via IIS in production).

In the case of large files I need to extend this timeout to a larger value. I've tried to achieve this in a number of ways:

  1. Request Header - Timeout of request in angular code. I used the following code to try to set the timeout header value but it doesn't effect the 120 seconds:

    export class AuthTokenInterceptor implements HttpInterceptor {
    
    constructor(private authContext: AuthContext) {
    }
    
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const authHeaderValue = this.authContext.getAuthenticationHeaderValue(req.url);
    
        if (authHeaderValue) {
            const authReq = req.clone({  headers:
              req.headers.set('Authorization', authHeaderValue)
                         .set('Timeout', '100000000000000000') });
    
            return next.handle(authReq);
        }
        return next.handle(req);
    }    }
    
  2. web.config - I've tried setting the httpRuntime timeout value in the web.config file to the following (but still times out at 120 seconds):

  3. Within IIS - I've tried setting the configuration of the "Limits" property in IIS and again, still times out at 120 seconds (and this has no relevance when I'm running through node server).

enter image description here

Has anyone been able to modify this 120 seconds in their Angular(2+) app requests?

Thanks for any pointers in advance!

NOTE: just for completeness, here's my asp.net core, controller method for uploading:

[HttpPost("Upload")]
public async Task<IActionResult> UploadAsync(IFormFile file)
{
    // Ensure the file has contents before processing.
    if (file == null || file.Length == 0)
        throw new ApiException("Csv file should not be null", HttpStatusCode.BadRequest)
            .AddApiExceptionResponseDetails(ErrorTypeCode.ValidationError, ErrorCode.BelowMinimumLength, SOURCE); 

    // Ensure the file is not over the allowed limit.
    if (file.Length > (_settings.MaxCsvFileSize * 1024))
        throw new ApiException("Max file size exceeded, limit of " + _settings.MaxCsvFileSize + "mb", HttpStatusCode.BadRequest)
            .AddApiExceptionResponseDetails(ErrorTypeCode.ValidationError, ErrorCode.ExceedsMaximumLength, SOURCE); 

    // Ensure the file type is csv and content type is correct for the file.
    if (Path.GetExtension(file.FileName) != ".csv" || 
        !Constants.CsvAcceptedContentType.Contains(file.ContentType.ToLower(CultureInfo.InvariantCulture)))
            throw new ApiException("Csv content only accepted").AddApiExceptionResponseDetails(ErrorTypeCode.ValidationError, ErrorCode.Invalid, SOURCE);

    // Read csv content.
    var content = await file.ReadCsvAsync<OrderCsvResponseDto>() as CsvProcessedResponseDto<OrderCsvResponseDto>;

    await ProcessBulkUpload(content);

    // Return information about the csv file.
    return Ok(content);
}

Note - when I run the web api via IIS Express then it times out, I've run it using the command host and it doesn't time out - seem's like this may be related to an IIS setting of sorts. The web api doesn't have a web.config file due to the new version of ASP.net Core I'm using but this piece of code doesn't seem to have any bearing on IIS Express when I run through it:

      var host = new WebHostBuilder()
                .UseStartup<Startup>()
                .UseKestrel(o => {

                    o.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(10);
                    o.ShutdownTimeout = TimeSpan.FromMinutes(10);
                    o.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(10);

                })
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseApplicationInsights()
                .Build();
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I will post this here in case anyone else comes across the same problem I was having. It turns out that running in IIS Express (or hosted IIS) that the config setting overrides whatever you have in code (maybe this is because the newer version of .net Core doesn't have a web.config file in the project - I'm not sure).

Anyway, I worked around this problem by carrying out the following steps:

Open IIS Express in your taskbar

enter image description here

Click on the app you are running (and wish to extend the request timeout for). Clicking the app shows the config file of the application. Double click to open the config file.

enter image description here

Apply the following setting to the aspNetCore section:

requestTimeout="00:20:00"

Example:

   <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" forwardWindowsAuthToken="false" requestTimeout="00:20:00" stdoutLogEnabled="false" />
      <httpCompression>
        <dynamicCompression>
          <add mimeType="text/event-stream" enabled="false" />
        </dynamicCompression>
      </httpCompression>
    </system.webServer>

And that's it!

NOTE: I am hosting the app in PaaS ASE - so cant configure IIS directly here. My solution for this was now to add a web.config file to the api project, and apply my setting within it. The build process honours the web.config you've got already instead of generating one on the fly and it will keep the changes needed. In my case, the web.config looked like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" forwardWindowsAuthToken="false" requestTimeout="00:20:00" stdoutLogEnabled="false" />
  </system.webServer>
</configuration>

Hopefully this helps others!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...