Ich mache eine UWP-App, die Dateien nach Facebook hochlädt, ich benutze einen benutzerdefinierten HttpContent, um die Dateien in 4k-Blöcken hochzuladen, um die Speichernutzung für große Dateien (> 100mb) zu minimieren und den Fortschritt zu melden.HttpClient liest die gesamte Datei vor dem Upload. UWP
Meine benutzerdefinierte 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;
}
}
Was ich erlebe (mit Fiedler) ist, dass die gesamte Datei im Speicher vor dem Upload beginnt geputtet wird (meine Fortschrittsanzeige 100% erreicht, bevor der Upload selbst beginnt).
Ich habe versucht, die TransferEncodingChunked
zu true
, und die Datei Inhalt Länge einstellen, aber das Problem bleibt.
Die Upload-Quelle befindet sich in einem PCL (wenn es darauf ankommt). Ich verwende die neueste Version von System.Net.Http
. Bei Bedarf benutze ich das genau so, wie es in der MediaFire SDK
verwendet wird. Danke für jede Hilfe.
EDIT: die Httpclient Nutzung Hinzugefügt:
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);
}
wahr ich nicht dieses Problem mit einem benutzerdefinierten beheben könnte HttpContent wurde meine Alternative einer StreamContent verwendet, und eine zu machen Stream Decorator, der beim Lesen Fortschritte gemeldet hat. Mit einem StreamContent streamt HttpClient den Inhalt, ohne ihn (alle) in den Speicher zu bringen. – DVD
Nicht genau, ich benutze einen benutzerdefinierten httpcontent, ich überprüfe bereits, dass mit einem Stream-Inhalt funktioniert es wie erwartet, ich will nur wissen, warum es nicht mit einem benutzerdefinierten httpcontent funktioniert, oder wenn es irgendeinen Weg es wäre. – DVD
Kannst du auch den Stückcode um HttpClient herum teilen? Übrigens. Ich würde in Betracht ziehen, Drahthai stattdessen zu verwenden (nicht sicher, ob das Hinzufügen von Fiddler als http-Proxy nicht mit dem Verkehr unordentlich ist). –