如何读取 IFormFile 文件,而不需要将文件上传到服务器,也不需要使用 MemoryStream。
有一种将文件上传到服务器的方法:
protected async Task<IActionResult> UploadFile(
IFormFile file,
string apiKey,
string folderForCryptionFile)
{
try
{
if (file == null || file.Length <= 0)
{
return BadRequest(new { message = "No file selected for upload" });
}
var userid = await _readUser.ReadUserIdByApiKey(apiKey);
var uploadsFolder = Path.Combine(folderForCryptionFile, $"User({userid})");
if (!Directory.Exists(uploadsFolder))
{
Directory.CreateDirectory(uploadsFolder);
}
double totalSizeFolder = GetSize.GetFolderSizeInMb(uploadsFolder);
double totalSizeFile = GetSize.GetFileSizeInMb(file);
if (totalSizeFolder + totalSizeFile > 75.0)
{
return BadRequest("The size of an individual folder should not exceed 75 MB");
}
var uniqueFileName = Guid.NewGuid().ToString() + "_" + file.FileName;
var filePath = Path.Combine(uploadsFolder, uniqueFileName);
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
return Ok();
}
catch (InvalidOperationException)
{
return BadRequest("User with this API key not found");
}
catch (Exception ex)
{
return Problem(ex.Message);
}
}
和这样的控制器方法:
[HttpPost("Upload")]
public async Task<IActionResult> UploadFiles(List<IFormFile> files, [FromHeader(Name = "ApiKey")] string apiKey)
{
var totalFiles = files.Count;
var successFiles = 0;
foreach (var file in files)
{
if (allowedFiles.allowedContentTypes.Contains(file.ContentType))
{
await UploadFile(file, apiKey, _paths.FolderForEncryptionFiles);
successFiles++;
}
else
{
continue;
}
}
if (successFiles == totalFiles)
{
return Ok($"All {totalFiles} files were successfully uploaded and saved.");
}
else if (successFiles > 0 && successFiles != totalFiles)
{
return Ok($"{successFiles} out of {totalFiles} files were successfully uploaded and saved.");
}
else
{
return BadRequest("No files were successfully uploaded.");
}
}
可以看到,它以 IFormFile 的形式接受来自客户端的文件,在控制器中,在加载文件之前,需要读取文件并将文件数据发送给第三方 API,并且由于无法将文件上传到服务器,因此无法使用File.OpenRead,所以选项仍然是MemoryStream,但它会使用大量内存,并且如果有很多文件和用户,然后使用 Dispose 将不再有帮助。
还有其他选项可以读取该文件吗?
IFormFile事实上,它是Stream从请求中获取的 的包装器。Stream它允许您使用OpenReadStream方法进行创建,您已经可以使用该方法来复制数据而无需将其保存到文件中。您已经在这里使用了这种方法:
因此,当将此文件提交给第三方API时,您可以尝试使用相同的方法。那些。如果您有权访问类似的流,
NetworkStream那么您可以使用CopyToAsync.如果您正在使用
HttpClient,您可以尝试将此流打包到Content:如果您有一些特殊的 API,那么很可能需要手动实现、读入缓冲区、以某种方式处理并进一步发送。