Отправка файла по чанку с помощью HttpWebRequest.GetRequestStream () - PullRequest
0 голосов
/ 01 июля 2018

У меня очень простая задача. В моем ASP.NET Core 2 я должен принять URL-адрес файла от пользователя и повторно передать двоичные данные файла в мой внутренний микросервис. Я пытаюсь сделать это без сохранения файла на диске или в памяти. Просто примите файл чанка и отправьте его по сети. Я написал этот код

int bytesToRead = 4096;
byte[] buffer = new Byte[bytesToRead];

// getting download stream
HttpWebRequest fileReq = (HttpWebRequest)HttpWebRequest.Create(fileUrl);
HttpWebResponse fileResp = (HttpWebResponse)fileReq.GetResponse();
if (fileReq.ContentLength > 0)
{
    fileResp.ContentLength = fileReq.ContentLength;
}

// getting upload stream
var downloadStream = fileResp.GetResponseStream();

HttpWebRequest uploadRequest = HttpWebRequest.CreateHttp("url_to_send_file_data");
uploadRequest.Method = "POST";
uploadRequest.ContentLength = fileResp.ContentLength;
uploadRequest.ContentType = "application/octet-stream";

var uploadStream = await uploadRequest.GetRequestStreamAsync();

int length = 0;
do
{
    length = await downloadStream.ReadAsync(buffer, 0, bytesToRead);

    await uploadStream.WriteAsync(buffer, 0, length);
    await uploadStream.FlushAsync();
}
while (length > 0);

// all file data in uploadStream._buffer so far
uploadStream.Close();

// only in this point request actually start
var result = await uploadRequest.GetResponseAsync();

downloadStream.Close();

Согласно руководствам и статьям, запрос должен быть запущен после uploadRequest.GetRequestStream(), и все uploadStream.WriteAsync() вызовы должны записывать данные непосредственно в сеть. Но фактически все данные файла записаны в uploadStream._buffer и отправлены в сеть только после GetResponseAsync() вызова.

Я пытался играть с uploadRequest.SendChunked свойствами и с заголовками HTTP, но не повезло.

Будет ли он полезным для любого предложения.

P.S. Да, я знаю о using(){}:)

1 Ответ

0 голосов
/ 01 июля 2018

Я не совсем уверен, что вы там делаете, но при условии, что у вас есть IFormFile из запроса POST, содержащего ваш файл, вы можете просто использовать его поток для передачи запроса, используя HttpClient:

private async Task SendFileAsync(IFormFile file, HttpClient client)
{
    var url = "url_to_send_file_data";

    using (var fileStream = file.OpenReadStream())
    using (var request = new HttpRequestMessage(HttpMethod.POST, url))
    {
        request.Content = new StreamContent(fileStream);

        var response = await client.SendAsync(request);
        response.EnsureSuccessStatusCode();
    }
}

Это позволит повторно использовать поток входящих файлов и использовать его для исходящего запроса.

...