Convertir HttpPostedFileBase en octet []

123

Dans mon application MVC, j'utilise le code suivant pour télécharger un fichier.

MODÈLE

 public HttpPostedFileBase File { get; set; }

VUE

@Html.TextBoxFor(m => m.File, new { type = "file" })

Tout fonctionne bien .. Mais j'essaie de convertir le champ de résultat en octet []. Comment puis-je faire cela

MANETTE

 public ActionResult ManagePhotos(ManagePhotos model)
    {
        if (ModelState.IsValid)
        {
            byte[] image = model.File; //Its not working .How can convert this to byte array
        }
     }
Pointeur nul
la source

Réponses:

259

Comme le dit Darin, vous pouvez lire à partir du flux d'entrée - mais j'éviterais de compter sur toutes les données disponibles en une seule fois. Si vous utilisez .NET 4, c'est simple:

MemoryStream target = new MemoryStream();
model.File.InputStream.CopyTo(target);
byte[] data = target.ToArray();

Il est assez facile d'écrire l'équivalent de CopyTo.NET 3.5 si vous le souhaitez. La partie importante est que vous lisez HttpPostedFileBase.InputStream.

Pour des raisons efficaces, vous pouvez vérifier si le flux renvoyé est déjà un MemoryStream:

byte[] data;
using (Stream inputStream = model.File.InputStream)
{
    MemoryStream memoryStream = inputStream as MemoryStream;
    if (memoryStream == null)
    {
        memoryStream = new MemoryStream();
        inputStream.CopyTo(memoryStream);
    }
    data = memoryStream.ToArray();
}
Jon Skeet
la source
Le premier exemple n'a pas fonctionné pour moi dans .NET4 (je n'ai pas essayé l'autre) - Cela n'a pas fonctionné lorsque je l'ai essayé avec un .png ou .jpg, mais cela a fonctionné lorsque j'ai utilisé un fichier .txt . N'importe quelle idée pourquoi :)
VoodooChild
2
@VoodooChild: Il est probable que quelque chose dans ce que vous faites est de traiter les données comme du texte. J'aurais besoin de plus de code pour savoir quoi. Je vous suggère de poser une autre question en donnant votre scénario complet.
Jon Skeet
6
ok cela a fonctionné pour moi, juste pour donner un peu de contexte - Merci! `Image img = Image.FromStream (fichier.InputStream); MemoryStream ms = nouveau MemoryStream (); img.Save (ms, ImageFormat.Jpeg); model.SiteLogo = ms.ToArray (); `
VoodooChild
7
Je trouvais que la position du flux d'entrée était à la fin du flux, donc j'ai dû ajouter la ligne model.File.InputStream.Position = 0;avant le code de Jon pour le faire fonctionner
Manish
2
@UweKeim: Eh bien oui, nous avons déjà une instruction using (pas une directive, btw) pour inputStream, et les deux feront référence au même objet. Pourquoi voudriez-vous vous en débarrasser deux fois?
Jon Skeet
27

Vous pouvez le lire à partir du flux d'entrée:

public ActionResult ManagePhotos(ManagePhotos model)
{
    if (ModelState.IsValid)
    {
        byte[] image = new byte[model.File.ContentLength];
        model.File.InputStream.Read(image, 0, image.Length); 

        // TODO: Do something with the byte array here
    }
    ...
}

Et si vous avez l'intention d'enregistrer directement le fichier sur le disque, vous pouvez utiliser la model.File.SaveAsméthode. Vous trouverez peut-être le billet de blog suivant utile.

Darin Dimitrov
la source
5
Le InputStream pour un HttpPostedFileBase est-il garanti pour renvoyer toutes ses données en un seul appel à Read? Il vaut mieux éviter cela dans la mesure du possible.
Jon Skeet