4

Controller:

private readonly Dictionary<string, Stream> streams;

        public ActionResult Upload(string qqfile, string id)
        {
            string filename;
            try
            {
                Stream stream = this.Request.InputStream;
                if (this.Request.Files.Count > 0)
                {
                    // IE
                    HttpPostedFileBase postedFile = this.Request.Files[0];
                    stream = postedFile.InputStream;
                }
                else
                {
                    stream = this.Request.InputStream;
                }

                filename = this.packageRepository.AddStream(stream, qqfile);
            }
            catch (Exception ex)
            {
                return this.Json(new { success = false, message = ex.Message }, "text/html");
            }

            return this.Json(new { success = true, qqfile, filename }, "text/html");
        }

method for adding stream:

        public string AddStream(Stream stream, string filename)
        {

            if (string.IsNullOrEmpty(filename))
            {
                return null;
            }

            string fileExt = Path.GetExtension(filename).ToLower();
            string fileName = Guid.NewGuid().ToString();
            this.streams.Add(fileName, stream);
        }

I'm trying read a binary stream like so:

Stream stream;
            if (!this.streams.TryGetValue(key, out stream))
            {
                return false;
            }

    private const int BufferSize = 2097152;

                            using (var binaryReader = new BinaryReader(stream))
                            {
                                int offset = 0;
                                binaryReader.BaseStream.Position = 0;
                                byte[] fileBuffer = binaryReader.ReadBytes(BufferSize); // THIS IS THE LINE THAT FAILS
    ....

When I view stream in debug mode it shows that it can be read = true, seek = true, lenght = 903234 etc.

but I keep getting: Cannot access a closed file

This works fine when I run mvc site locally/debug mode (VS IIS) and DOES NOT WORK when in "RELEASE" mode (when site is published to iis).

what am I doing wrong?

ShaneKm
  • 20,823
  • 43
  • 167
  • 296

2 Answers2

8

Found solution here:

uploading file exception

Solution:

add "requestLengthDiskThreshold" on production envirenment

<system.web>
<httpRuntime executionTimeout="90" maxRequestLength="20000" useFullyQualifiedRedirectUrl="false" requestLengthDiskThreshold="8192"/>
</system.web>
ShaneKm
  • 20,823
  • 43
  • 167
  • 296
  • shane! i am also encountering this error where would i add this? in the web config file? in the production environment? thanks :) – Albert Laure Oct 17 '13 at 08:56
  • in your web.config file between clause – ShaneKm Oct 17 '13 at 12:38
  • Microsoft bug when value is defaulted. Resolution is setting RequestLengthDiskThreshold explicitly, as stated. – Suncat2000 Apr 26 '18 at 15:34
  • Is this value in bytes or kilobytes? I set mine to 65536 and now it's working fine even though my uploaded files total about 179KB... even though the microsoft doc says bytes. https://learn.microsoft.com/en-us/dotnet/api/system.web.configuration.httpruntimesection.requestlengthdiskthreshold?view=netframework-4.7.2 – komodosp Oct 08 '18 at 15:51
0

It would seem you are relying on the lifetime of an object you do not control (properties of the HttpRequest object). If you wish to store the data of the stream it would be safer to copy that data immediately to a byte array or similar

you could change AddStream to

    public string AddStream(Stream stream, string filename)
    {

        if (string.IsNullOrEmpty(filename))
        {
            return null;
        }

        string fileExt = Path.GetExtension(filename).ToLower();
        string fileName = Guid.NewGuid().ToString();
        var strLen = Convert.ToInt32(stream.Length);
        var strArr = new byte[strLen];
        stream.Read(strArr, 0, strLen);
        //you will need to change the type of streams acccordingly
        this.streams.Add(filename,strArr); 
    }

you can then use the array when you need the data of the stream which gives you complete control of the lifetime of the object the data is stored in

Rune FS
  • 21,497
  • 7
  • 62
  • 96