我正在製作一個將文件上傳到Facebook的UWP應用程序,我使用自定義的HttpContent以4k塊的形式上傳文件,以儘量減少大文件(> 100mb)的內存使用量並報告進度。HttpClient在上傳前讀取整個文件。 UWP
我定製HttpContent UploadWithProgressHttpContent:
class UploadWithProgressHttpContent : HttpContent
{
private readonly IProgress<OperationProgress> _progress;
private readonly OperationProgress _data;
private readonly Stream _file;
private readonly int _bufferSize;
private readonly CancellationToken _token;
public UploadWithProgressHttpContent(
IProgress<OperationProgress> progress,
OperationProgress data,
Stream file,
int bufferSize,
CancellationToken token)
{
_progress = progress;
_data = data;
_file = file;
_bufferSize = bufferSize;
_token = token;
}
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
return CopyStreamWithProgress(_file, stream, _progress, _token, _data, _bufferSize);
}
public static async Task<Stream> CopyStreamWithProgress(
Stream source,
Stream destination,
IProgress<OperationProgress> progress,
CancellationToken token,
OperationProgress progressData,
int bufferSize
)
{
int read, offset = 0;
var buffer = new byte[bufferSize];
using (source)
{
do
{
read = await source.ReadAsync(buffer, 0, bufferSize, token);
await destination.WriteAsync(buffer, 0, read, token);
offset += read;
progressData.CurrentSize = offset;
progress.Report(progressData);
} while (read != 0);
}
return destination;
}
}
什麼我遇到(使用招)是整個文件被存儲在上傳開始前(我的進度條達到100%上傳甚至開始前的推杆)。
我曾嘗試將TransferEncodingChunked
設置爲true
,並設置文件內容的長度,但問題依然存在。
上傳來源在PCL中(如果有的話)。我正在使用最新版本的System.Net.Http
。如果需要,我使用的方式與MediaFire SDK
完全相同,謝謝你的幫助。
編輯:添加HttpClient的用法:
public async Task<T> Upload<T>(Stream fileStream, string fileName)
{
var handler = new HttpClientHandler();
var cli = new HttpClient(handler);
foreach (var header in Headers)
{
cli.DefaultRequestHeaders.Add(header.Key, header.Value);
}
var parameters = new MultipartFormDataContent();
foreach (var parameter in Parameters)
{
parameters.Add(new StringContent(parameter.Value), parameter.Key);
}
if (fileStream != null)
{
var fileContent = new UploadWithProgressHttpContent(ProgressOperation, ProgressData, fileStream,
_chunkBufferSize, Token, fileStream.Length);
fileContent.Headers.ContentType = new MediaTypeHeaderValue(MimeTypeHelper.GetMimeType(fileName));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue(StreamParamName);
fileContent.Headers.ContentDisposition.FileName = fileName;
fileContent.Headers.ContentLength = fileStream.Length;
parameters.Add(fileContent, StreamParamName);
}
var req = new HttpRequestMessage(method, Path) { Content = parameters };
if (fileStream != null)
req.Headers.TransferEncodingChunked = true;
var completionOption = HttpCompletionOption.ResponseContentRead;
var resp = await cli.SendAsync(req, completionOption, Token).ConfigureAwait(false);
return await DeserializeObject<T>(resp);
}
我無法修復使用自定義HttpContent這個問題,我的替代是使用StreamContent,並作出流裝飾器報道讀取進展。通過使用StreamContent,HttpClient可以在不將內容全部帶入內存的情況下對內容進行流式傳輸。 – DVD
不完全是,我使用的是自定義的httpcontent,我已經檢查過使用流的內容,它的工作方式和預期的一樣,我只是想知道爲什麼它不能與自定義的httpcontent一起工作,或者如果有任何方式的話。 – DVD
你能分享一下HttpClient的代碼嗎?順便說一句。我會考慮使用Wire Shark來代替(不確定是否將httpd代理添加爲fiddler並不會影響流量)。 –