使用HttpWebRequest.GetRequestStream()按块发送文件

时间:2018-06-30 23:00:25

标签: c# asp.net-core .net-core httpwebrequest

我有一个非常简单的任务。在我的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 :(得分:0)

我不确定您在做什么,但是假设您有一个包含文件的POST请求中的IFormFile,您可以使用它的流通过HttpClient传递给请求: / p>

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();
    }
}

这将直接重用传入的文件流并将其用于传出请求。