J'essaie d'utiliser CSVHelper pour générer un fichier CSV et le renvoyer à un navigateur afin que l'utilisateur puisse sélectionner un emplacement de sauvegarde et un nom de fichier, puis sauvegarder les données.
Le site Web est basé sur MVC. Voici le code du bouton jQuery que j'utilise pour effectuer l'appel (les données sont des représentations Json sérialisées d'une liste DTO):
$.ajax({
type: "POST",
url: unity.baseUrl + "common/ExportPayments",
data: data
});
Voici le code du contrôleur:
[HttpPost]
public FileStreamResult ExportPayments()
{
MemoryStream ms = new MemoryStream();
StreamWriter sw = new StreamWriter(ms);
CsvWriter writer = new CsvWriter(sw);
List<Payment_dto> pd = _commonService.GetPayments();
foreach (var record in pd)
{
writer.WriteRecord(record);
}
sw.Flush();
return new FileStreamResult(ms, "text/csv");
}
Ce qui semble ne donner exactement rien - invoquer les étapes de la méthode dans le bit de code correct mais la réponse est vide, sans parler d'offrir à l'utilisateur une boîte de dialogue de fichier pour enregistrer les données. J'ai parcouru ce code, qui récupère des données du service, les écrit et ne génère aucune erreur. Alors qu'est-ce que je fais mal?
EDIT: Renvoyer cette ...
return File(ms.GetBuffer(), "text/csv", "export.csv");
... me donne une réponse, constituée des données au format csv que j'attends. Mais le navigateur ne semble toujours pas savoir quoi en faire - aucune option de téléchargement n’est offerte à l’utilisateur.
Essayez ci-dessous le code:
public FileStreamResult ExportPayments()
{
var result = WriteCsvToMemory(_commonService.GetPayments()());
var memoryStream = new MemoryStream(result);
return new FileStreamResult(memoryStream, "text/csv") { FileDownloadName = "export.csv" };
}
public byte[] WriteCsvToMemory(IEnumerable<Payment_dto> records)
{
using (var memoryStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memoryStream))
using (var csvWriter = new CsvWriter(streamWriter))
{
csvWriter.WriteRecords(records);
streamWriter.Flush();
return memoryStream.ToArray();
}
}
Mettre à jour
Vous trouverez ci-dessous comment passer un modèle de type complexe à une méthode d'action utilisant la méthode HTTP GET
. Je ne préfère pas cette approche, cela vous donne simplement une idée qu'il existe une approche pour y parvenir.
Modèle
public class Data
{
public int Id { get; set; }
public string Value { get; set; }
public static string Serialize(Data data)
{
var serializer = new JavaScriptSerializer();
return serializer.Serialize(data);
}
public static Data Deserialize(string data)
{
var serializer = new JavaScriptSerializer();
return serializer.Deserialize<Data>(data);
}
}
Action:
[HttpGet]
public FileStreamResult ExportPayments(string model)
{
//Deserialize model here
var result = WriteCsvToMemory(GetPayments());
var memoryStream = new MemoryStream(result);
return new FileStreamResult(memoryStream, "text/csv") { FileDownloadName = "export.csv" };
}
Vue:
@{
var data = new Data()
{
Id = 1,
Value = "This is test"
};
}
@Html.ActionLink("Export", "ExportPayments", new { model = Data.Serialize(data) })
Essayez dans le contrôleur:
HttpContext.Response.AddHeader("content-disposition", "attachment; filename=payments.csv");
Pourrait également l'utilisateur mot-clé dynamique pour la conversion des données
Code de @Lin
public FileStreamResult ExportPayments()
{
var result = WriteCsvToMemory(_commonService.GetPayments()());
var memoryStream = new MemoryStream(result);
return new FileStreamResult(memoryStream, "text/csv") { FileDownloadName = "export.csv" };
}
public byte[] WriteCsvToMemory(dynamic records)
{
using (var memoryStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memoryStream))
using (var csvWriter = new CsvWriter(streamWriter))
{
csvWriter.WriteRecords(records);
streamWriter.Flush();
return memoryStream.ToArray();
}
}