Umbraco Forms Custom Upload Field - Store string value of file
Wondering if anyone can help?
I am 'rolling my own' upload field - The current upload field is not behaving well when the form is revisited (it erases all uploads if no new ones are added and can sometimes lock up files and cause issues etc.).
I just need some guidance on saving the single string url of the uploaded file within the form - at the moment nothing gets saved!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Umbraco.Forms.Core;
using Umbraco.Forms.Core.Providers.FieldTypes;
public class IRFUploader : Umbraco.Forms.Core.FieldType
{
//private List<Object> _value = new List<object>();
public IRFUploader()
{
Id = new Guid("2e41d645-0b7e-402d-aedf-a18afb168a85");
Name = "Custom file upload";
Description = "Renders an upload field.";
Icon = "icon-cloud-upload ";
DataType = FieldDataType.String;
FieldTypeViewName = "FieldType.IRFUploader.cshtml";
}
public override IEnumerable<string> ValidateField(Form form, Field field, IEnumerable<object> postedValues, HttpContextBase context)
{
IList<HttpPostedFileBase> files = context.Request.Files.GetMultiple(field.Id.ToString());
//foreach (HttpPostedFileBase file in files)
//{
// if (file.FileName != "")
// {
// // Check something is there!!!
// return new[]
// {
// form.Id.ToString() + " - " + field.Id.ToString() + " - " + file.FileName // <--- YES IT IS!
// };
// }
//}
return Enumerable.Empty<string>();
}
public override IEnumerable<object> ProcessSubmittedValue(Field field, IEnumerable<object> postedValues, HttpContextBase context)
{
// HOW DO I PROCESS AND STORE THE STRING VALUE?
return base.ProcessSubmittedValue(field, postedValues, context);
}
public override IEnumerable<object> ConvertFromRecord(Field field, IEnumerable<object> storedValues)
{
// HOW DO I GET THE STRING VALUE?
return base.ConvertFromRecord(field, storedValues);
}
public override IEnumerable<object> ConvertToRecord(Field field, IEnumerable<object> postedValues, HttpContextBase context)
{
// HOW DO I SAVE THE STRING VALUE?
return base.ConvertToRecord(field, postedValues, context);
}
}
Any help or steer in the right direction much appreciated! :-)
It's not the most elegant and there is one downside - Once a file is uploaded you can replace it, it will always be saved, but you cannot remove the current file completely... maybe someone has a solution to this, but for my purposes it works!
Basically if a value exists I create a session with the key being the GUID and the value being the URL in the view...
@using Umbraco.Web
@model Umbraco.Forms.Mvc.Models.FieldViewModel
<input type="file" name="@Model.Name" id="@Model.Id" multiple
@if(Model.Mandatory){<text> data-val="true" data-val-required="@Model.RequiredErrorMessage"</text>} />
@if (Model.Values != null && Model.Values.Any())
{
Session.Add(Model.Id, Model.Value); // <-- HERE!
<p>
<strong>Current File/s:</strong><br/>
@foreach (Dictionary<string, string> dictionaryObject in Model.Values)
{
@*
The model.values contains a list of dictionary objects with a single item
With the key being the full path to the file
And the value being the filename
*@
if (dictionaryObject.Count > 0)
{
var fileInfo = dictionaryObject.First();
<a href="@fileInfo.Key" target="_blank">@fileInfo.Value</a><br/>
<input type="hidden" name="@(Model.Name)_file_@(fileInfo.Value)" value="@fileInfo.Key" />
}
}
</p>
}
Now all I need to do is handle that value inside the 'ProcessSubmittedValue' method....
private List<Object> myValue = new List<object>();
public override IEnumerable<object> ProcessSubmittedValue(Field field, IEnumerable<object> postedValues, HttpContextBase context)
{
string fieldFolder = field.Id.ToString();
string newFolder = DateTime.Now.ToUniversalTime().ToString("ddMMyyyyhhmmss");
string dir = "/media/forms/" + fieldFolder + "/" + newFolder + "/";
IList<HttpPostedFileBase> files = context.Request.Files.GetMultiple(field.Id.ToString());
foreach (HttpPostedFileBase file in files)
{
if (file.FileName != "")
{
// Create directory
if (!Directory.Exists(HttpContext.Current.Server.MapPath(dir)))
{
Directory.CreateDirectory(HttpContext.Current.Server.MapPath(dir));
}
// Save the file
file.SaveAs(HttpContext.Current.Server.MapPath(dir + SafeUrl(file.FileName)));
// Add string to the form
myValue.Add(dir + SafeUrl(file.FileName));
// Remove any old file
if (context.Session[field.Id.ToString()] != null)
{
string oldFile = context.Session[field.Id.ToString()].ToString();
string oldDir = oldFile.Substring(0, oldFile.LastIndexOf("/"));
// Remove old directory
if (Directory.Exists(HttpContext.Current.Server.MapPath(oldDir)))
{
Directory.Delete(HttpContext.Current.Server.MapPath(oldDir),true);
}
}
}
}
// If nothing has been added but a previous value exists in session add to the list and remove the session!
if (myValue.Count() == 0 && context.Session[field.Id.ToString()] != null)
{
myValue.Add(context.Session[field.Id.ToString()].ToString());
}
// Clean up session
context.Session.Remove(field.Id.ToString());
return myValue;
// NOTHING TO BE DONE
//return base.ProcessSubmittedValue(field, postedValues, context);
}
And that works for me! High five if I saved you a few days of puzzling this one out :-)
Umbraco Forms Custom Upload Field - Store string value of file
Wondering if anyone can help?
I am 'rolling my own' upload field - The current upload field is not behaving well when the form is revisited (it erases all uploads if no new ones are added and can sometimes lock up files and cause issues etc.).
I just need some guidance on saving the single string url of the uploaded file within the form - at the moment nothing gets saved!
My view is currently just the generic -
And my code looks like this...
Any help or steer in the right direction much appreciated! :-)
Took me a few days, but I have found a solution!
It's not the most elegant and there is one downside - Once a file is uploaded you can replace it, it will always be saved, but you cannot remove the current file completely... maybe someone has a solution to this, but for my purposes it works!
Basically if a value exists I create a session with the key being the GUID and the value being the URL in the view...
Now all I need to do is handle that value inside the 'ProcessSubmittedValue' method....
And that works for me! High five if I saved you a few days of puzzling this one out :-)
UPDATE:
So my forms have been running for almost a year without any hitches and then lo-and-behold I get a call requesting the removal of an upload.... doh!
I fixed the problem momentarily by commenting out the following line
This did clear things down which got me thinking...
What if we upload a file (e.g. "delete.txt") and then checked for this filename?
Then check the string here
And don't add it if the current file is called 'delete.txt'
Just a thought...
is working on a reply...