Я использую компонент Syncfusion Blazor Uploader, подробно описанный [здесь] (https://blazor.syncfusion.com/documentation/file-upload/getting-started#without-server-side-api-endpoint), чтобы загрузить файл. в хранилище BLOB-объектов Azure. Компонент находится в клиентском проекте и вызывает службу для маршрутизации вызова на контроллер, который находится в серверном проекте. Вот код, когда пользователь добавляет новый файл (на стороне клиента)
private async Task OnChange(UploadChangeEventArgs args)
{
foreach (var file in args.Files)
{
try
{
var serializedFile = JsonSerializer.Serialize<Syncfusion.Blazor.Inputs.FileInfo>(file.FileInfo);
await RemoteService.UploadStudyGuide(serializedFile);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
В настоящее время у меня есть требования — отправить его через службу, которая, в свою очередь, вызывает контроллер. Вот метод внутри сервиса
public async Task UploadStudyGuide(string serializedFile)
{
var response =
await _httpClient.PostAsJsonAsync("StudyGuide/Upload", serializedFile);
}
а вот контроллер:
[HttpPost("Upload")]
public async Task Upload([FromBody] string serializedFile)
{
string devConnectionString = "myConnectionString";
string blobContainerName = "myContainerName";
var file = JsonSerializer.Deserialize<Syncfusion.Blazor.Inputs.FileInfo>(serializedFile);
try
{
// Azure connection string and container name passed as argument to get the Blob reference of container.
// Provide your container name as second argument to this method. Example, upload-container.
var container = new BlobContainerClient(devConnectionString, blobContainerName);
// Method to create our container if it doesn’t exist.
var createResponse = await container.CreateIfNotExistsAsync();
// If successfully created our container then set a public access type to Blob.
if (createResponse != null && createResponse.GetRawResponse().Status == 201)
await container.SetAccessPolicyAsync(Azure.Storage.Blobs.Models.PublicAccessType.Blob);
// Method to create a new Blob client.
var blob = container.GetBlobClient($"/ASPTDEV/StudyGuides/{file.Name}");
// If the blob with the same name exists, then we delete the blob and its snapshots.
await blob.DeleteIfExistsAsync(Azure.Storage.Blobs.Models.DeleteSnapshotsOption.IncludeSnapshots);
// Create a file stream and use the UploadSync method to upload the blob.
using (var fileStream = new FileStream(blob.BlobContainerName, FileMode.Create))
{
await blob.UploadAsync(fileStream, new BlobHttpHeaders { ContentType = $"{file.MimeContentType}" });
fileStream.Close();
}
}
catch (Exception e)
{
Response.Clear();
Response.StatusCode = 204;
Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "File failed to upload";
Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = e.Message;
}
}
Файл успешно загружается в большой двоичный объект без ошибок. Но когда это происходит, размер равен 0 байтам. Я пробовал с заголовками типов контента и без них, а также с несколькими разными файлами с одинаковым результатом.
Если это поможет, вот класс Syncfusion, который я сериализую:
public class FileInfo
{
[JsonPropertyName("fileSource")]
public string FileSource { get; set; }
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("input")]
public DOM Input { get; set; }
[JsonPropertyName("list")]
public DOM List { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
[DefaultValue(null)]
[JsonPropertyName("rawFile")]
public object RawFile { get; set; }
[JsonPropertyName("size")]
public double Size { get; set; }
[JsonPropertyName("status")]
public string Status { get; set; }
[JsonPropertyName("statusCode")]
public string StatusCode { get; set; }
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("mimeContentType")]
public string MimeContentType { get; set; }
[JsonPropertyName("lastModifiedDate")]
public DateTime LastModifiedDate { get; set; }
[JsonPropertyName("validationMessages")]
public ValidationMessages ValidationMessages { get; set; }
}
Это код, который вызывает у вас проблему:
using (var fileStream = new FileStream(blob.BlobContainerName, FileMode.Create))
{
await blob.UploadAsync(fileStream, // this is the problem.
Вы создаете новый (то есть совершенно пустой) FileStream
. Затем вы просите клиент BLOB-объектов загрузить этот пустой объект fileStream
. Итак, вы получаете пустой BLOB-объект. Нулевая длина.
Вы можете записать свои данные напрямую, используя BlobClient
, вообще не нуждаясь в FileStream
:
await blob.UploadAsync(BinaryData.FromString(serializedFile));
Из вашего примера неясно, как именно вы хотите хранить данные serializedFile
в Blob, поэтому первое решение может быть не тем, что вам нужно.
Например, если вам нужно сериализовать объект FileInfo
, вы можете использовать поток. Но вместо того, чтобы создавать пустой FileStream и писать его, вы можете попросить BlobClient
открыть поток, а затем написать в него из JsonSerializer
:
using (var stream = await blob.OpenWriteAsync(true))
{
await JsonSerializer.SerializeAsync(stream, file);
}
Рад, что это помогло!
Вы совершенно правы. Спасибо, это исправлено.