Anthares
Anthares

Reputation: 1059

Umbraco MediaService / Umbraco MediaItem not saving

I am trying to read an image file from the file system and save it as a MediaItem in Umbraco.

This is the code I put together:

MemoryStream uploadFile = new MemoryStream();
using (FileStream fs = File.OpenRead(tempFilename))
{
    fs.CopyTo(uploadFile);

    HttpPostedFileBase memoryfile = new MemoryFile(uploadFile, mimetype, Path.GetFileName(src.Value));
    IMedia mediaItem = _mediaService.CreateMedia(Path.GetFileName(src.Value), itNewsMediaParent, "Image");
    mediaItem.SetValue("umbracoFile", memoryfile);
    _mediaService.Save(mediaItem);
    src.Value = library.NiceUrl(mediaItem.Id);
}

Unfortunately, it seems that Umbraco is not able to save the file in the media folder. It does create the node in the Media tree, it sets the correct width, height, and all the rest. However it points to /media/1001/my_file_name.jpg. The media section already contains several images, and the next "ID" that should be used is "1018". Also, if I check inside /media/1001 there is no sign of my_file_name.jpg.

I've also verified that the SaveAs method of memoryfile (which is a HttpPostedFileBase) never gets called.

Can anyone assist me and point me to the right direction to sort this out?

Upvotes: 2

Views: 4793

Answers (2)

dmportella
dmportella

Reputation: 4724

The Media object reacts differently for some object types pass to it, in the case of files there is an override in the child classes that handles an HTTPPostedFile which is only created during a file post event however the base class HttpPostedFileBase (which is what Umbraco references) can by inherited and implemented so you can pass files to the media service and have Umbraco create the right file path etc.

In the example below I have created a new class called FileImportWrapper that inherits from HttpPostedFilebase I then proceed to override all properties and implement my version of them.

For content type i used the code example presented in this stackoverflow post (File extensions and MIME Types in .NET).

See the example code below.

Class Code

    public sealed class FileImportWrapper : HttpPostedFileBase
    {
        private FileInfo fileInfo;

        public FileImportWrapper(string filePath)
        {
            this.fileInfo = new FileInfo(filePath);
        }

        public override int ContentLength
        {
            get
            {
                return (int)this.fileInfo.Length;
            }
        }

        public override string ContentType
        {
            get
            {
                return MimeExtensionHelper.GetMimeType(this.fileInfo.Name);
            }
        }

        public override string FileName
        {
            get
            {
                return this.fileInfo.FullName;
            }
        }

        public override System.IO.Stream InputStream
        {
            get
            {
                return this.fileInfo.OpenRead();
            }
        }

        public static class MimeExtensionHelper
        {
            static object locker = new object();
            static object mimeMapping;
            static MethodInfo getMimeMappingMethodInfo;

            static MimeExtensionHelper()
            {
                Type mimeMappingType = Assembly.GetAssembly(typeof(HttpRuntime)).GetType("System.Web.MimeMapping");
                if (mimeMappingType == null)
                    throw new SystemException("Couldnt find MimeMapping type");
                ConstructorInfo constructorInfo = mimeMappingType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null);
                if (constructorInfo == null)
                    throw new SystemException("Couldnt find default constructor for MimeMapping");
                mimeMapping = constructorInfo.Invoke(null);
                if (mimeMapping == null)
                    throw new SystemException("Couldnt find MimeMapping");
                getMimeMappingMethodInfo = mimeMappingType.GetMethod("GetMimeMapping", BindingFlags.Static | BindingFlags.NonPublic);
                if (getMimeMappingMethodInfo == null)
                    throw new SystemException("Couldnt find GetMimeMapping method");
                if (getMimeMappingMethodInfo.ReturnType != typeof(string))
                    throw new SystemException("GetMimeMapping method has invalid return type");
                if (getMimeMappingMethodInfo.GetParameters().Length != 1 && getMimeMappingMethodInfo.GetParameters()[0].ParameterType != typeof(string))
                    throw new SystemException("GetMimeMapping method has invalid parameters");
            }

            public static string GetMimeType(string filename)
            {
                lock (locker)
                    return (string)getMimeMappingMethodInfo.Invoke(mimeMapping, new object[] { filename });
            }
        }
    }

Usage Code

IMedia media = ApplicationContext.Current.Services.MediaService.CreateMedia("image test 1", -1, Constants.Conventions.MediaTypes.Image);

this.mediaService.Save(media); // called it before so it creates a media id

FileImportWrapper file = new FileImportWrapper(IOHelper.MapPath("~/App_Data/image.png"));

media.SetValue(Constants.Conventions.Media.File, file);

ApplicationContext.Current.Services.MediaService.Save(media);

I hope this helps you and others with the same requirement.

Upvotes: 3

oliver254
oliver254

Reputation: 31

To Save media, I found this method with MediaService. However, I think it's possible another method more refined

    [HttpPost]
    public JsonResult Upload(HttpPostedFileBase file)
    {
        IMedia mimage;

        // Create the media item
        mimage = _mediaService.CreateMedia(file.FileName, <parentId>, Constants.Conventions.MediaTypes.Image);
        mimage.SetValue(Constants.Conventions.Media.File, file);
        _mediaService.Save(mimage);  

        return Json(new { success = true});
    }

Upvotes: 3

Related Questions