2011-10-12 1 views
2

Je dispose d'un formulaire de commentaires simple qui permet à mes utilisateurs de consigner des commentaires et de télécharger éventuellement des fichiers liés au problème. Les fichiers peuvent être de n'importe quel format, pas seulement des images.Stockage et récupération de fichiers dans une base de données de la bonne façon avec MVC 3

Le code côté serveur sur le contrôleur ressemble à ceci:

[HttpPost] 
    public ActionResult Create(Entry entry) 
    { 
     try 
     { 
      foreach (string inputTagName in Request.Files) 
      { 
       HttpPostedFileBase file = Request.Files[inputTagName]; 

       if (file != null && file.ContentLength > 0) 
       { 
        using (MemoryStream ms = new MemoryStream()) 
        { 
         file.InputStream.CopyTo(ms); 

         db.Files.Add(new Models.File 
         { 
          Entry = entry, 
          FileName = Path.GetFileName(file.FileName), 
          FileContents = ms.GetBuffer() 
         }); 
        } 
       } 
      } 

      entry.Status = Status.Open; 
      entry.Severity = Severity.Medium; 
      entry.DateSubmitted = DateTime.Now; 

      db.Entries.Add(entry); 
      db.SaveChanges(); 

      return View("Complete"); 
     } 
     catch 
     { 
      return View("Error"); 
     } 
    } 

J'ai aussi une action de contrôleur qui me permet de télécharger la base de données entière dans un zip et de l'envoyer à mon navigateur:

public ActionResult Download() 
    { 
     MemoryStream fileStream = new MemoryStream(); 
     StringBuilder csv = new StringBuilder(); 
     csv.AppendLine("Id,Summary,Description,Company,Name,Email,Telephone,Version,Area,Date Submitted,Notes,Resolution,Date Resolved"); 

     using (ZipFile zip = new ZipFile()) 
     { 
      foreach (Entry entry in db.Entries.ToList()) 
      { 
       csv.AppendFormat("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12}", 
           entry.Id, 
           entry.Summary, 
           entry.Description, 
           entry.Company.Name, 
           entry.Name, 
           entry.Email, 
           entry.Telephone, 
           entry.Version.Number, 
           entry.Area, 
           entry.DateSubmitted, 
           entry.Notes, 
           entry.Resolution, 
           entry.DateResolved); 

       if (entry.Files.Count > 0) 
       { 
        foreach (FeedbackManager.Models.File file in entry.Files) 
        { 
         using (MemoryStream ms = new MemoryStream()) 
         { 
          ms.Write(file.FileContents, 0, file.FileContents.Length); 
          ms.Flush(); 
          zip.AddEntry(entry.Id+"_"+file.FileName, ms.GetBuffer()); 
         } 
        } 
       } 
      } 

      zip.AddEntry("feedback.csv", csv.ToString()); 

      zip.Save(fileStream); 
     } 

     return File(fileStream.GetBuffer(), "application/zip", String.Format("FeedbackToDate_{0}.zip", DateTime.Now.Date.ToShortDateString())); 
    } 

Le problème im avoir est de lire les données de fichier hors de la base de données, le fichier zip est corrompu de quelque façon et je ne suis pas capable de l'ouvrir, si j'exclus les fichiers, je peux ouvrir le fichier zip et je peux lire csv bien.

Quelle est la bonne façon de retirer ces fichiers de la base de données, dois-je d'abord enregistrer dans le système de fichiers? Les données du fichier sont-elles corrompues? Comment puis-je conserver les données binaires brutes afin que le contenu ne soit pas affecté?

Merci

Répondre

3

Utilisez MemoryStream.ToArray() au lieu de MemoryStream.GetBuffer() ->http://msdn.microsoft.com/en-us/library/system.io.memorystream.toarray.aspx

MemoryStream.GetBuffer() peut également renvoyer les octets non utilisés qui ne font pas partie du contenu.

+0

Un grand merci, qui a résolu le problème. J'ai également utilisé 'MemoryStream.ToArray()' lors de l'enregistrement du tableau d'octets dans la base de données, ce qui devrait faire en sorte que seuls les octets réels du fichier soient sauvegardés en premier lieu, n'est-ce pas? – James

0

Vous faites l'hypothèse que les données ne sont pas correctement insérées dans la base de données.

lors du téléchargement du fichier que vous devez faire quelque chose comme ceci:

int FileLen; 
System.IO.Stream MyStream; 

FileLen = file.ContentLength; 
byte[] input = new byte[FileLen]; 

MyStream = file.InputStream; 
MyStream.Read(input, 0, FileLen); 

Affectez ensuite entrée à votre champ de base de données comme ceci:

FileContents = input; 

Je ne suis pas sûr de ce que vous utilisez comme une base de données principale, mais si vous utilisez 2008, utilisez le type de données varbinary (max).

+0

N'est-ce pas équivalent à: 'file.InputStream.CopyTo (ms); FileContents = ms.ToArray() '? – James

+0

Le type de données DB est également 'varbinary (max)', qui est le type de données defualt lors de l'utilisation du type 'byte []' pour les propriétés d'entité dans EntityFramework CodeFirst – James

+0

Oui, .CopyTo fera la même chose. Merci d'avoir fait remarquer cela. Après d'autres recherches, il peut même être le moyen le plus sûr de le faire. –

Questions connexes