using System;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Forms.Core;
using Umbraco.Forms.Core.Models;
using Umbraco.Forms.Core.Searchers;
using Umbraco.Forms.Web.Helpers;
namespace MyFormsExtensions
{
public class ExportToHtml : ExportType
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IFormRecordSearcher _formRecordSearcher;
public ExportToHtml(
IHostEnvironment hostEnvironment,
IHttpContextAccessor httpContextAccessor,
IFormRecordSearcher formRecordSearcher)
: base(hostEnvironment)
{
_httpContextAccessor = httpContextAccessor;
_formRecordSearcher = formRecordSearcher;
Name = "Export as HTML";
Description = "Export entries as a single HTML report";
Id = new Guid("4117D352-FB41-4A4C-96F5-F6EF35B384D2");
FileExtension = "html";
Icon = "icon-article";
}
public override string ExportRecords(RecordExportFilter filter)
{
var view = "~/Views/Partials/Forms/Export/html-report.cshtml";
EntrySearchResultCollection model = _formRecordSearcher.QueryDataBase(filter);
return ViewHelper.RenderPartialViewToString(_httpContextAccessor.GetRequiredHttpContext(), view, model);
}
}
}@model Umbraco.Forms.Core.Searchers.EntrySearchResultCollection
@{
var submissions = Model.Results.ToList();
var schemaItems = Model.Schema.ToList();
}
<h1>Form Submissions</h1>
@foreach (var submission in submissions)
{
var values = submission.Fields.ToList();
for (int i = 0; i < schemaItems.Count; i++)
{
<strong>@schemaItems[i].Name</strong> @values[i].Value
<br />
}
<hr />
}using Umbraco.Cms.Core.Composing;
using Umbraco.Forms.Core.Providers.Extensions;
using Umbraco.Forms.TestSite.Business.ExportTypes;
namespace MyFormsExtensions
{
public class TestComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.FormsExporters().Add<ExportToHtml>();
}
}
}using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Forms.Core;
using Umbraco.Forms.Core.Models;
using Umbraco.Forms.Core.Searchers;
namespace MyFormsExtensions
{
public class ExportToTextFiles : ExportType
{
private readonly IFormRecordSearcher _formRecordSearcher;
public ExportToTextFiles(
IHostingEnvironment hostingEnvironment,
IFormRecordSearcher formRecordSearcher)
: base(hostingEnvironment)
{
_formRecordSearcher = formRecordSearcher;
this.Name = "Export as text files";
this.Description = "Export entries as text files inside a zip file";
this.Id = new Guid("171CABC9-2207-4575-83D5-2A77E824D5DB");
this.FileExtension = "zip";
this.Icon = "icon-zip";
}
/// <summary>
/// We do not implement this method from the interface
/// As this method is called from ExportToFile that we also override here & is expecting the file contents as a string to be written as a stream to a file
/// Which would be OK if we were creating a CSV or a single based file that can have a simple string written as a string such as one large HTML report or XML file perhaps
/// </summary>
public override string ExportRecords(RecordExportFilter filter) => throw new NotImplementedException();
/// <summary>
/// This gives us greater control of the export process
/// </summary>
/// <param name="filter">
/// This filter contains the date range & other search parameters to limit the entries we are exporting
/// </param>
/// <param name="filepath">
/// The filepath that the export file is expecting to be served from
/// So ensure that the zip of text files is saved at this location
/// </param>
/// <returns>The final file path to serve up as the export - this is unlikely to change through the export logic</returns>
public override string ExportToFile(RecordExportFilter filter, string filepath)
{
// Before Save - Check Path, Directory & Previous File export does not exist
string pathToSaveZipFile = filepath;
// Check our path does not contain \\
// If not, use the filePath
if (filepath.Contains('\\') == false)
{
pathToSaveZipFile = HostingEnvironment.MapPathContentRoot(filepath);
}
// Get the directory (strip out \\ if it exists)
var dir = filepath.Substring(0, filepath.LastIndexOf('\\'));
var tempFileDir = Path.Combine(dir, "text-files");
// If the path does not end with our file extension, ensure it's added
if (pathToSaveZipFile.EndsWith("." + FileExtension) == false)
{
pathToSaveZipFile += "." + FileExtension;
}
// Check that the directory where we will save the ZIP file temporarily exists
// If not just create it
if (Directory.Exists(tempFileDir) == false)
{
Directory.CreateDirectory(tempFileDir);
}
// Check if the zip file exists already - if so delete it, as we have a new update
if (File.Exists(pathToSaveZipFile))
{
File.Delete(pathToSaveZipFile);
}
// Query the DB for submissions to export based on the filter
EntrySearchResultCollection submissions = _formRecordSearcher.QueryDataBase(filter);
// Get the schema objects to a list so we can get items using position index
var schemaItems = submissions.schema.ToList();
// We will use this to store our contents of our file to save as a text file
var fileContents = string.Empty;
// For each submission we have build up a string to save to a text file
foreach (EntrySearchResult submission in submissions.Results)
{
// The submitted data for the form submission
var submissionData = submission.Fields.ToList();
// For loop to match the schema position to the submission data
for (int i = 0; i < schemaItems.Count; i++)
{
// Concat a string of the name of the field & its stored data
fileContents += schemaItems[i].Name + ": " + submissionData[i] + Environment.NewLine;
}
// Now save the contents to a text file
// Base it on the format of the record submission unique id
var textFileName = Path.Combine(tempFileDir, submission.UniqueId + ".txt");
File.WriteAllText(textFileName, fileContents);
// Reset fileContents to be empty again
fileContents = string.Empty;
}
// Now we have a temp folder full of text files
// Generate a zip file containing them & save that
ZipFile.CreateFromDirectory(tempFileDir, pathToSaveZipFile);
// Tidy up after ourselves & delete the temp folder of text files
if (Directory.Exists(tempFileDir))
{
Directory.Delete(tempFileDir, true);
}
// Return the path where we saved the zip file containing the text files
return pathToSaveZipFile;
}
}
}