简体   繁体   中英

How to initialize byte array as an OUT parameter in C# before proper array length is known

I'm having trouble with a webmethod used to download a file to a calling HTTPHandler.ashx file. The handler calls the webmethod as follows:

byte[] docContent;
string fileType;
string fileName;
string msgInfo = brokerService.DownloadFile(trimURL, recNumber, out docContent, out fileType, out fileName);

In the called webmethod, I have to initialize the byte array before using it or I get compiler errors on all the return statements:

The out parameter 'docContents' must be assigned to before control leaves the current method

I tried setting it to an empty array but that causes the Buffer.BlockCopy method to fail:

Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
mscorlib
  at System.Buffer.BlockCopy(Array src, Int32 srcOffset, Array dst, Int32 dstOffset, Int32 count)

I know I need to initialize it but I don't know the length of the array needed until I access the database. Through debugging I've verified all the code works except for the Buffer.BlockCopy:

    public string DownloadFile(string trimURL
        , string TrimRecordNumber
        , out byte[] docContents
        , out string returnFiletype
        , out string returnFilename)
    {
        docContents = new byte[0];
        returnFiletype = null; returnFilename = null;
        try
        {
            ConnectToTrim(trimURL);
            if (!db.IsValid)
                return "CRITICAL: Database Is NOT Valid";
            Record myRec = db.GetRecord(TrimRecordNumber);
            if (myRec == null)
                return "CRITICAL: Record not found.";
            uint bufferSize = 10000;
            int documentLength = myRec.DocumentSize;
            byte[] result = new byte[documentLength];
            byte[] buffer = new byte[bufferSize];
            uint bytesRead;
            uint totalBytesRead = 0;
            TRIMSDK.IStream docStream = myRec.GetDocumentStream(string.Empty, false, string.Empty);
            while (totalBytesRead < documentLength)
            {
                docStream.RemoteRead(out buffer[0], 10000, out bytesRead);
                for (int i = 0; i < bytesRead; i++)
                {
                    result[totalBytesRead] = buffer[i];
                    totalBytesRead += 1;
                }
            }
            returnFiletype = myRec.Extension;
            returnFilename = myRec.SuggestedFileName;
            Buffer.BlockCopy(result, 0, docContents, 0, result.Length); 
            return string.Format("OK-Document for recordnumber({0}): {1}.{2} - size: {3} bytes",
                TrimRecordNumber, returnFilename, returnFiletype, Convert.ToString(documentLength)); 
        }
        catch (Exception ex)
        {
            return LogException(ex, "CRITICAL: Exception in DownloadFile method has been logged:", trimURL, 100);
        } 
    } 

You can start by initializing it to null. Just prior to calling Buffer.BlockCopy , allocate and initialize it to the proper length.

This would look like:

public string DownloadFile(string trimURL
    , string TrimRecordNumber
    , out byte[] docContents
    , out string returnFiletype
    , out string returnFilename)
{
    docContents = null;

    //...

        returnFiletype = myRec.Extension;
        returnFilename = myRec.SuggestedFileName;
        docContents = new byte[result.Length]; // Allocate appropriately here...
        Buffer.BlockCopy(result, 0, docContents, 0, result.Length); 
        return ...

Alternatively, you can just directly allocate and copy the results into docContents - eliminating the need for result entirely. You will still need to initailize to null at the start if you want to leave your overall flow control alone, however.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM