I want to edit the large file (Size ~ 50 MB) via Microsoft IIS Admin API and mentioned is the official documentation link (https://learn.microsoft.com/en-us/iis-administration/api/files#manipulating-file-content-apifilescontent).
Microsoft IIS Admin API has some limitations that it can't edit a file that is more than 30 MB in size so it needs to be done in chunks.
I am using the Refit library to make calls to IIS Admin.
var totalSize = content.Length;
for (int i = 0; i < totalSize / 1000; i++)
{
var lowerLimit = i == 0 ? 0 : 1000 * i;
var upperLimit = i == 0 ? 999 : i == totalSize / 1000 ? (totalSize % 1000 - 1) : (i+1)*1000 - 1;
var contentLength = i == totalSize/1000 ? totalSize % 1000 : 1000;
var headers = new Dictionary<string, string> { { "Content-Length", $"{contentLength}" }, { "Content-Range", $"bytes {lowerLimit}-{upperLimit}/{totalSize}" } };
await _client.EditFileUnderDirectoryInChunks(content, fileId, AccessTokenHeaderValue, headers, cancellationToken).ConfigureAwait(false);
}
Refit Client
[Put("/api/files/content/{fileId}")]
[Headers("Content-Type: application/octet-stream")]
Task EditFileUnderDirectoryInChunks(
[Body] Stream content,
string fileId,
[Header("Access-Token")] string accessToken, [HeaderCollection] IDictionary<string, string> headers,
CancellationToken cancellationToken = default);
When my for loop runs it run successfully for the first iteration but in the second iteration I was getting below error
The issue is resolved now by sending the data in chunks and previously I was sending entire Stream data to edit file API method of IIS Admin API.
Below is the final code
if (content.Length > 25000000) // Size Limit 25 MB
{
var totalSize = content.Length;
var streamChunks = SplitStreamIntoChunks(content, 25000000).ToArray();
for (int i = 0; i <= totalSize / 25000000; i++)
{
var lowerLimit = i == 0 ? 0 : 25000000 * i;
var upperLimit = i == 0 ? (25000000 - 1) : i == totalSize / 25000000 ? ((i * 25000000) + (totalSize % 25000000 - 1)) : (i + 1) * 25000000 - 1;
var contentLength = i == totalSize / 25000000 ? totalSize % 25000000 : 25000000;
var contentRange = $"bytes {lowerLimit}-{upperLimit}/{totalSize}";
await _client.EditFileUnderDirectoryInChunks(new MemoryStream(streamChunks[i]), fileId, AccessTokenHeaderValue,
contentLength, contentRange, cancellationToken).ConfigureAwait(false);
}
}
private static IEnumerable<byte[]> SplitStreamIntoChunks(Stream stream, int chunkSize)
{
var bytesRemaining = stream.Length;
while (bytesRemaining > 0)
{
var size = Math.Min((int)bytesRemaining, chunkSize);
var buffer = new byte[size];
var bytesRead = stream.Read(buffer, 0, size);
if (bytesRead <= 0)
break;
yield return buffer;
bytesRemaining -= bytesRead;
}
}