Upload stream to virtual path

Vote:
 

This may not be an episerver question per se but I'll take a shot at maybe finding an answer to my question.

At the time we store the profile pictures of our users outside of EPiServer but I'm working on a way to get them into the built in file manager. Before the file was stored to disk in a specific folder and then stored with an ID in an SQL table. The new code uploads the picture to the file manager using a function with the following piece of code:

publicstring UploadFile(Stream fileContent, UnifiedDirectory directory, string fileName, string fileExtension, bool overwriteExisting)
{
    ...

   
UnifiedFile uFile = directory.CreateFile(fileName + "." + fileExtension);
    Stream s = uFile.Open(FileMode.CreateNew);

    byte[] buffer = newbyte[fileContent.Length];
    int numBytesToRead = (int)fileContent.Length;

    fileContent.Read(buffer, 0, numBytesToRead);

    s.Write(buffer, 0, buffer.Length);
    s.Close();

    fileContent.Close();

    return uFile.VirtualPath;

}

When calling this function and giving the first input parameter fileUpload.PostedFile.InputStream this code works great, however I want to resize them before uploading them. I've got a fairly long function for this so I won't post it here but when uploading the resized image using our "old" storing procedure (and stored it to disk) I used the following code to do so:

using (System.Drawing.Bitmap img = ResizeImage(new System.Drawing.Bitmap(profilePicture.PostedFile.InputStream), 151, 500, ResizeOptions.MaxWidth))
{

    img.Save(root + fileDirectory + folder + newPictureName, System.Drawing.Imaging.ImageFormat.Png);

}

When I now want to resize and upload to the EPiServer file manager I can't really figure out how to go about. The file is created with the correct size in the file manager, both file and image wise, but when I open it I just get a big X-image like the kind you typically get in IE when a file is missing. I don't really know how to convert a Bitmap like System.Drawing.Bitmap img = ResizeImage(new System.Drawing.Bitmap.profilePicture.PostedFile.InputStream), 151, 500, ResizeOptions.MaxWidth); to a Stream that's compatible with my UploadFile-function.

Are you with me? How do I do this? I've managed to create a MemoryStrem that at least compiles but that is what gives me the X image. Like I said, this is perhaps not a EPiServer related question but hope that someone can help me out and perhaps it will be helpful to someone else in the future.

#54007
Sep 29, 2011 8:43
Vote:
 

Hi!

You shold be able to simply call img.Save( uStream, System.Drawing.Imaging.ImageFormat.Png);
where "uStream" is the stream returned by uFile.Open();

/johan

 

#54012
Sep 29, 2011 10:16
Vote:
 

The upload function seems to be working but as soon as I try to do something besides uploading the stream from the file picker I get an "empty" image. Or maybe I don't understans your answer. Where does the uStream and uFile come in?

#54013
Sep 29, 2011 10:26
Vote:
 

Hi,

uFile from your code sample in the first post, uStream would be what you called "s":

Heres how it could look like:

 

UnifiedFile uFile = directory.CreateFile(fileName + "." + fileExtension);

Stream s = uFile.Open(FileMode.CreateNew);

using (System.Drawing.Bitmap img = ResizeImage(new System.Drawing.Bitmap(profilePicture.PostedFile.InputStream), 151, 500, ResizeOptions.MaxWidth))
{
    img.Save(s, System.Drawing.Imaging.ImageFormat.Png);
}

 

 

#54014
Sep 29, 2011 10:29
Vote:
 

Yeah, but that part of the code is fully functional and I wouldn't like to mess with it. It's how I call that function correctly that is the question. The "Stream fileContent" input parameter works great when I call it and asign it with fileUpload.PostedFile.InputStream but I first need to do something like this, but that gives me the faulty image:

System.Drawing.Bitmap img = ResizeImage(new System.Drawing.Bitmap(fileUpload.PostedFile.InputStream), 151, 500, ResizeOptions.MaxWidth);

MemoryStream ms = newMemoryStream();
img.Save(ms, ImageFormat.Png);
fileHandler.UploadFile(ms, HostingEnvironment.VirtualPathProvider.GetDirectory(path.VirtualPath + subDir) asUnifiedDirectory,  userID, "png", true);

As soon as I asign it with ms instead of fileUpload.PostedFile.InputStream something goes wrong. It's as if something is wrong with the ms-stream.

#54015
Edited, Sep 29, 2011 10:35
Vote:
 

Ok, I see, you dont want to modify your UploadFile() function?

Try to simply reset (seek) the MemoryStream to its beginning before calling UploadFile().

img.Save(ms, ...);
ms.Seek( 0, SeekOrigin.Begin );
UploadFile(ms, ... );

But; in order to preserve server memory, it would be beneficial if the MemoryStream-step could be
avoided altogether and the (resized)img could save to the UnifiedFile's stream directly.

/jiohan

 

#54017
Sep 29, 2011 10:40
Vote:
 

That worked, thanks!

Yes, you are right about the whole memory preserving but that would mean one function for each kind of upload, right? I was trying to keep the code to a minimun.

#54018
Sep 29, 2011 10:46
Vote:
 

Not necessarily, there are numerous ways you can refactor that function, here's one way that contains two overloaded UploadFile() functions, one with the same arguments as before, and one new that lets you pass in a lambdaexpression for the code to write to the uniifiedFileStream.

        public string UploadFile(Stream fileContent, UnifiedDirectory directory, string fileName, string fileExtension, bool overwriteExisting)
        {
            return UploadFile(directory, fileName, fileExtension, overwriteExisting, (Stream writeStream) =>
            {
                int bytesRead = 0;
                int numBytesToRead = 2048;
                byte[] buffer = new byte[numBytesToRead];
                
                while(0 < (bytesRead = fileContent.Read(buffer, 0, numBytesToRead))
                {
                    writeStream.Write(buffer, 0, bytesRead);
                }    

                fileContent.Close();
            });
        }

        public string UploadFile(UnifiedDirectory directory, string fileName, string fileExtension, bool overwriteExisting, Action<Stream> writeStream)
        {
            UnifiedFile uFile = directory.CreateFile(fileName + "." + fileExtension);
            Stream s = uFile.Open(FileMode.CreateNew);

            writeStream(s);
            s.Close();

            return uFile.VirtualPath;
        }

With this modification, you could now call the UploadFile() function like this (when dealing with your resized bitmaps)
        UploadFile(Directory, fileName, fileExtension, overwriteExisting, (Stream s) => {

            img.Save( s, ImageFormat.Png );

        });
    

/johan

 

 

#54019
Sep 29, 2011 11:06
Vote:
 

Wow, thanks! Appreciate the effort!

#54020
Sep 29, 2011 11:09
Vote:
 

Thanks johan. Helped me alot.

#55856
Dec 21, 2011 9:29
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.