2009-12-24 5 views
3

J'essaye de servir un fichier txt fait à partir de la base de données en utilisant une action. L'action est la suivante:asp.net mvc desservant txt est tronqué

public ActionResult ATxt() 
{ 
    var articulos = _articulosService.ObteTotsArticles(); 
    return File(CatalegATxt.ATxt(articulos), "text/plain"); 
} 

et la classe CatalegATxt est:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Text; 
using WebDibaelsaMVC.DTOs.Busqueda; 

namespace WebDibaelsaMVC.TxtLib 
{ 
    public static class CatalegATxt 
    { 
     public static Stream ATxt(IEnumerable<ArticuloBusquedaDTO> articles) 
     { 
      var stream = new MemoryStream(); 
      var streamWriter = new StreamWriter(stream, Encoding.UTF8); 
      foreach (ArticuloBusquedaDTO article in articles) 
      { 
       streamWriter.WriteLine(article.ToStringFix()); 
      } 
      stream.Seek(0, SeekOrigin.Begin); 
      return stream; 
     } 

     public static string ToStringFix(this ArticuloBusquedaDTO article) 
     { 
      string result = ""; 
      result += article.CodigoArticulo.PadRight(10, ' ').Substring(0, 10); 
      result += article.EAN.Trim().PadLeft(13, '0').Substring(0, 13); 
      result += article.NombreArticulo.PadRight(100, ' ').Substring(0, 100); 
      result += article.Marca.PadRight(100, ' ').Substring(0, 100); 
      result += article.Familia.PadRight(50, ' ').Substring(0, 50); 
      result += article.PrecioCesion.ToStringFix(); 
      result += article.PVP.ToStringFix(); 
      return result; 
     } 

     private static string ToStringFix(this double numero) 
     { 
      var num = (int)Math.Round(numero * 100, 0); 
      string result = num.ToString().PadLeft(10, '0'); 
      return result; 
     } 
    } 
} 

il écrit simplement les lignes de fichiers basé sur les choses que je suis arrivé de la base de données. Mais quand je regarde le fichier, il semble tronqué. Le fichier fait environ 8Mb. J'ai également essayé de convertir en byte[] avant de retourner d'ATxt avec le même résultat.

Une idée?

Merci,

Carles

Mise à jour: j'ai essayé aussi de servir XML du même contenu et il devient également tronqué. Il n'est pas tronqué sur les données (je pensais que c'était un caractère EOF) mais il tronque au milieu d'une étiquette ...

+0

Q rapide, pour les tests txt et xml les tailles de fichier retournées sont-elles de la même longueur? Cela pourrait nous aider à le retrouver. – Rippo

+0

Si vous suivez le contenu de CatelegAText.ATxt dans votre méthode ActionResult ci-dessus, contient-elle les données correctes avant de le renvoyer? – glenatron

+0

@Rippo: Ils n'ont pas la même longueur. txt est un peu de Mb, xml est inférieur à 1 Mo. –

Répondre

4

j'avais exactement le même problème. Le fichier texte sera toujours renvoyé comme tronqué.

Il m'a traversé l'esprit que cela pourrait être un problème de "rinçage", et en effet il l'était. La mémoire tampon de l'auteur n'a pas été vidée à la fin de l'opération - puisqu'il n'y a pas de bloc d'utilisation, ou l'appel Close() - qui serait automatiquement vidé.

Vous devez appeler:

streamWriter.Flush(); 

avant MVC prend en charge le flux.

Voilà comment votre méthode devrait ressembler à:

public static Stream ATxt(IEnumerable<ArticuloBusquedaDTO> articles) 
{ 
    var stream = new MemoryStream(); 
    var streamWriter = new StreamWriter(stream, Encoding.UTF8); 
    foreach (ArticuloBusquedaDTO article in articles) 
    { 
     streamWriter.WriteLine(article.ToStringFix()); 
    } 
    // Flush the stream writer buffer 
    streamWriter.Flush(); 
    stream.Seek(0, SeekOrigin.Begin); 
    return stream; 
} 

Hope this helps!

Miroslav

+0

Super! C'était ça. Merci. –

0

Vous voulez probablement fermer le MemoryStream. Il pourrait être tronqué car il attend encore plus de données. Ou pour rendre les choses encore plus simples, essayez quelque chose comme ceci:

public static byte[] ATxt(IEnumerable<ArticuloBusquedaDTO> articles) 
{ 
    using(var stream = new MemoryStream()) 
    { 
     var streamWriter = new StreamWriter(stream, Encoding.UTF8); 
     foreach (ArticuloBusquedaDTO article in articles) 
     { 
      streamWriter.WriteLine(article.ToStringFix()); 
     } 

     return stream.ToArray(); 
    } 
} 
+0

J'ai déjà essayé de le faire avec le même résultat. En outre, fermer le flux avant de le retourner entraîne une erreur (la vue essaie d'accéder à un flux fermé ...) –

3

Pourquoi utilisez-vous un ActionResult?

ASP.NET MVC 1 a un FileStreamResult pour ce que vous faites. Il attend un objet Stream et le renvoie.

public FileStreamResult Test() 
{ 
    return new FileStreamResult(myMemoryStream, "text/plain"); 
} 

Cela devrait fonctionner correctement pour ce que vous voulez faire. Pas besoin de faire de conversions.

Dans votre cas, il suffit de changer votre méthode à ceci:

public FileStreamResult ATxt() 
{ 
    var articulos = _articulosService.ObteTotsArticles(); 
    return new FileStreamResult(CatalegATxt.ATxt(articulos), "text/plain"); 
} 
+0

Je pensais que 'FileStreamResult' étend' ActionResult' et c'est la même chose. La fonction 'File' renvoie aussi un' FileStreamResult' ... –

+0

FileStreamResult étend FileResult. Il est spécialement conçu pour envoyer un flux au client. Je l'ai utilisé régulièrement pour envoyer des fichiers Excel à des utilisateurs qui sont dans le voisinage de 10-15 Mo et ne les ont jamais tronqués. – thorkia

+0

FileResult étend ActionResult, mais gère la sortie différemment. Si vous voulez envoyer un fichier qui est stocké sur le disque dur, vous devez utiliser FileResult Si vous voulez envoyer le contenu d'un fichier, vous devez utiliser FileStreamResult – thorkia