2017-06-16 3 views
1

J'ai un simple http server où les gens téléchargent des fichiers et je les compresse juste et les enregistre sur le disque. C'est ce que je fais, je pense que les gens comprendront mieux avec le codeModifier le flux dans C#

/// <summary> 
/// Client uploads files through here 
/// </summary> 
private static void Server_ProcessRequest(HttpListenerContext context) 
{ 
    // I know that context.Request.InputStream starts like: ------WebKitFormBoundaryePkpFF7tjBAqx29L 
    // and it also ends with that boundary 

    // 1. I read from context.Request.InputStream and skip the headers 
    // (I read until I find 4 new lines) 

    // 2. I then write the file to disk 
    // var sizeOfFile = context.Request.ContentLength64; 
    // etc... read from stream 

    // 3. create a new stream in order to compress file later 
    var newStream = System.IO.File.Open("FileJustCreated"); 

    // 4. MySealedLibraryThatICannotModify.CompressFile(newStream,"CompressedFileLocation.zip");   
} 

Ma question ici est de savoir comment puis-je éviter d'écrire le fichier sur le disque? Je ne peux pas passer context.Request.InputStream à la méthode qui compresse le fichier car il contient des en-têtes et d'autres éléments qui ne font pas partie du fichier. Ce serait génial si je pouvais créer une méthode qui retournera un nouveau flux. Les fichiers peuvent être grands et je ne veux pas tout contenir en mémoire donc je cherchais à créer une méthode comme le System.IO.File.OpenRead où il retourne un flux où seule la partie que vous lisez est en mémoire. Je sais que je peux utiliser une bibliothèque différente pour compresser les fichiers, mais ce sera bien si je m'en tiens à cette bibliothèque et apprends quelque chose de nouveau.

+2

L'approche typique serait ici pour envelopper un flux avec un autre flux (personnalisé) qui suit le nombre d'octets consommés et refuse de délivrer des données passées cette point. Vous consommez généralement le flux d'origine au point souhaité avant de l'emballer. Je peux probablement creuser une implémentation de ce que j'ai de l'histoire ancienne si cela pouvait aider ... (J'avais l'habitude de faire exactement cela dans protobuf-net) –

+1

ouf, a pris un peu de creuser, mais: 'SubStream.cs': https: //github.com/mgravell/protobuf-net/blob/fd39e2f464273cfe942ab5ab793a7087ae881220/protobuf-net/SubStream.cs –

+0

Pourquoi ne pas simplement passer un flux partiellement lu à 'CompressFile'? Est-ce qu'il réinitialise réellement le flux au début avant de lire? Je pense que vous pouvez juste passer à l'endroit où vous voulez commencer à utiliser le flux original et le transmettre, en supposant qu'il le lit d'une manière raisonnablement raisonnable. – Servy

Répondre

0

Vous pouvez écrire dans la mémoire au lieu d'un fichier:

using (var buffer = new MemoryStream()) 
{ 
    context.Request.InputStream.CopyTo(buffer, sizeOfFile); 
    MySealedLibraryThatICannotModify.CompressFile(buffer, path); 
} 
+3

"Les fichiers peuvent être volumineux et je ne veux pas tout garder en mémoire" –