FileStream and writing out in chunks

hi all,

i have a byteArray i read into from a httpposted file, i would like to write it to a new filestream in chunks of a size i specify. I can write the file out no problem at once, using myFileStream.Write(byteArray,0,postedFile.Length) but i want to break it up into chunks so that it stores smaller amounts at a time and doesn't kill the aspnet_wp.

i have tried
FileStream newFile = new FileStream(fullSavePath + sFilename, FileMode.Create);
int pos = 0;
int length = 128;
while(pos < nFileLen)
{
if(length > (nFileLen - pos))
{
length = nFileLen - pos;
}
newFile.Write(myData,pos,length);
pos = int.Parse(newFile.Length.ToString());
}

and while it writes the correct amount of the file, and it appears on the file system, i cant open it, and it seems corrupt. Can someone tell me what im doing wrong

thanks

mcm




Answer this question

FileStream and writing out in chunks

  • XMLUser

    it is not causing the file to be uploaded to you in chunks (if you set a break point you will see that you already have the full file from the client once your postback gets called) ...
  • Regulus

    yes to a browser.

    i have been working on one "idea" so far. It involves sending the position integer that was in that formula above and storing it in my Image class (im using a facade implementation so i have access to the current users images, info, etc from the entire project).

    Anyways im trying to invoke some sort of refreshing page into an iframe to provide a status bar that refreshes itself through some javascript. Im stuck on getting the page to display before the postback is called. If you know of any way to display some sort of "uploading" message on a form before the file is posted i'd love to hear it.

    Ideally i'd like a status bar that appears in some section of the current window, but right now i'd settle for a span or panel just showing up with some text that says its uploading and to wait. But i can't figure it out!

    thanks

    mcm



  • CrystalDev

    just curious why you are doing this step

    pos = int.Parse(newFile.Length.ToString());

    you know the previous value of pos, and you know the amount of data you wrote (length) you can just add the two.

    FileStream newFile = new FileStream(fullSavePath + sFilename, FileMode.Create);
    int pos = 0;
    int length = 128;
    while(pos < nFileLen)
    {
    if(length > (nFileLen - pos))
    {
    length = nFileLen - pos;
    }
    newFile.Write(myData,pos,length);
    pos += length;

    }

    I would also not modify the length variable in the loop as you are doing in the loop as if you were coming accross smaller blocks midway it would cause a problem (but you are not).

    I am also unsure on your comment regarding "Killing the worker process" could you explain a bit more


  • mwharton

    thanks i changed that line to your suggestion, i know exactly why i did that, because i've been on this problem four like 12 hours :o! thanks for pointing it out. I've also changed the size to 16kb chunks and it seems to work okay. now i just have to figure out how to display some sort of status info.

    thanks,
    mcm



  • Nathan Liebke

    Sorry for the delay must have missed an alert. Ok I think this utility http://community.assistedsolutions.com/blogs/SlickUpload/ will do exactly what you want. Your worry is that the file is being loaded completely into memory right This cannot be handled by using a filestream etc but this is free and does it.

    Cheers,

    Greg


  • ThE_lOtUs

    cool thanks,

    i've since re-written my method to read and write chunks of any size (im setting them to 16k now) but it flushes the memory during the read and writes bits at a time, it's quite neat. i will polish it up and post it here for your information in a couple days.

    thanks again!



  • jose-luisp

    Just use a bit of javascript to show it (attach a javascript function to show an "uploading message" when they clic the submit button.

    Generally you will be better off this way as the majority of the operation is in the uploading of the file to the server not the processing of the file on the server.

    Cheers,

    Greg


  • IsshouFuuraibou

    i have attempted that, i used a simple javascript attached to the onpress event of a button, all it did was upload the file and show the js after the file was uploaded. I can't seem to do it in the order

    1) postback to show DIV tag
    2) Continue uploading while maintaining the input file.



  • ajhuddy

    thanks a lot.

    i tried an example almost exactly the same and it didn't work, however, i did another alternative that seems to work .

    I created a submit button using normal HTML <input type="submit">

    on SERVER CLICK runs the protected upload event

    on client click runs the js that shows the div, and it works great. But back to my original question. I am now uploading in chunks to my file stream. Is this at all any different than writing it all at once I dont understand the benefit of what i am doing because im not flusing the stream or anything, when i use Flush() it re-writes the next block of data over the last. I just want to make sure im not going to cripple the worker process when i upload a file.

    Heres what i have.

    FileStream newFile = new FileStream(fullSavePath + sFilename, FileMode.Create);

    //upload in chunks

    int pos = 0;
    int chunkSize = int.Parse(ConfigurationSettings.AppSettings["ulChunkSize"].ToString());
    while(pos < nFileLen)
    {
    chunkSize = chunkSize > (nFileLen - pos) chunkSize = nFileLen - pos : chunkSize;
    newFile.Write(myData,pos,chunkSize);

    //newFile.Flush(); <- WHEN I USED THIS IT JUST RE-WROTE THE NEXT 16b over the last.

    pos += chunkSize;
    SessionManager.Current.UploadedBytes = pos;
    }
    newFile.Close();



  • Evok

    here is a quick example I found on the web (the javascipt function is showing an alert but you could easily make it do something else such as showing a div which was previously hidden).

    <%@ Page Language="C#" %>
    <script runat="server">
    public void Page_Load(Object sender, EventArgs E) {
    btnSubmit.Attributes.Add("onclick",if(confirm('Are you sure everything is correct ')== false) return false;");
    }
    void btnSubmit_Click(object sender, EventArgs e) {
    Message.Text = "You entered your name as: " + txtName.Text;
    }
    </script>
    <html>
    <head>
    </head>
    <body>
    <form runat="server">
    Name: <asp:Textbox id="txtName" runat="server"/>
    <asp:Button id="btnSubmit" onclick="btnSubmit_Click" runat="server" Text="Submit"></asp:Button><br/>
    <asp:Label id="Message" runat="server"/>
    </form>
    </body>
    </html>


  • John Clark

    thanks for the response.

    i think i understand what your saying. that my byteArray is already full of the entire file

    (also on another point, i managed to get Flush to work i was spcifying 16bytes at a time to flush, not 16Kb)

    so how can i upload in chunks is it feasable should i just go while(httpPostedFile.Read() and only read into the dataArray parts at a time

    i am doing something like this:

    byte[] myData = new Byte[nFileLen];

    myFile.InputStream.Read(myData, 0, nFileLen);

    then i do some checking on the file (reading the first 18 bytes or so to determine what type of image it is)

    then i am using the same code i showed you to write it out in chunks to a new filestream.
    Should i modify it to only read in chunks

    i dont particularly care how it gets done (chunks or not) but i do want to be sure that the worker process is going to flush itself properly and not hog all the RAM.

    again, thanks for the help



  • MikeB123

    Cool, although I don't think it will help your original problem as the entirety of the upload process will have already occurred by the time the code gets executed (its not streaming from the client but instead writing an already existent byte array to a file, unless I am mistaken).

    Greg


  • Sid Singhvi

    to a webbrowser


  • FileStream and writing out in chunks