Forum Discussion

Nicolas_Menant's avatar
Mar 20, 2008

Structure FileTransferContext and file_data

Hi,

 

 

i try to create an windows API to retrieve an external class from a BIGIP, update it and then upload it again on the box.

 

 

I have something that seems strange:

 

 

in the SDK for the structure FileTransferContext it says that file_data is of type char[]

 

 

or when i try to compile my code it says: cannot implicity convert type 'string' to 'byte[]'.

 

 

When i did the download of the file i had to make an explicit cast (char) FTC.file_data[j] to make it work.

 

 

Is it possible the SDK is wrong or am i missing something (which is quite possible since i have developped anything since a long long time)

 

 

Thanks for your help!

 

 

Here is part of my code:

 

 

 

iControl.SystemConfigSyncFileTransferContext FTC = new iControl.SystemConfigSyncFileTransferContext();
int exit = 0;
int i, j;
string element;
       
for (i = 0; i < listBox_class.Items.Count; i++)
{
  element = "\""+listBox_class.Items[\i].ToString()+"\",\n";
  FTC.file_data = new byte[element.Length];
  for (j = 0; j < element.Length; j++)
    FTC.file_data[j] = (byte)((int)element[j]);
  if (j == 0)
    FTC.chain_type = iControl.CommonFileChainType.FILE_FIRST_AND_LAST;
  else if (j == (element.Length - 1))
    FTC.chain_type = iControl.CommonFileChainType.FILE_MIDDLE;
  else
    FTC.chain_type = iControl.CommonFileChainType.FILE_LAST;
  element = element.Remove(0);
  my_interface.SystemConfigSync.upload_file(filename, FTC);
}

 

 

Another question:

 

 

When i use upload_file, it looks like it appends the new data to the existing file, is it possible to make it overwrite the previous file ? or do i have to delete the file before doing the upload ?

 

 

Thanks

4 Replies

  • char[] is the happy medium I took on the SDK to cover all languages. Essentially it will be converted to a base64 string across the wire so for .NET that would be an array of bytes (byte[]).

     

     

    There is a sample in the SDK for ConfigSync that illustrates most of the ConfigSync interfaces. Since your code looks like C, here's the routine in ConfigSyncMain.cs file in the SDK's ConfigSync sample:

     

     

    void handle_upload(string local_file, string config_name)
    {
      ConfigSync.SystemConfigSyncFileTransferContext ctx = new ConfigSync.SystemConfigSyncFileTransferContext();
      bool bContinue = true;
      ctx.chain_type = CommonFileChainType.FILE_FIRST;
      long chunk_size = 1024;
      long total_bytes = 0;
      FileStream fs = new FileStream(local_file, FileMode.Open);
      BinaryReader r = new BinaryReader(fs);
      while (bContinue)
      {
        ctx.file_data = r.ReadBytes(Convert.ToInt32(chunk_size));
        if ( ctx.file_data.Length != chunk_size )
        {
          // At the end.  Check to see if it is the first request also.
          if ( 0 == total_bytes )
          {
            ctx.chain_type = CommonFileChainType.FILE_FIRST_AND_LAST;
          }
          else
          {
            ctx.chain_type = CommonFileChainType.FILE_LAST;
          }
          bContinue = false;
        }
        total_bytes += ctx.file_data.Length;
        
        // Upload bytes.
        ConfigSync.upload_configuration(config_name, ctx);
        // Move to middle 
        ctx.chain_type = CommonFileChainType.FILE_MIDDLE;
        Console.WriteLine("Uploaded " + total_bytes + " bytes");
      }
    }

     

     

    Now, this uses the upload_configuration() method, but the upload_file() method works the same way. Also, this doesn't do you much good if you want to use a string (as opposed to a file read with BinaryReader) as input. To get a byte array from a string, you'll want to use the System.Text.ASCIIEncoding classes GetBytes() method. Here's a wrapper function that converts a string into a byte array.

     

     

    public static byte[] StrToByteArray(string str)
    {
      System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
      return encoding.GetBytes(str);
    }

     

     

    Also, this method shows how to "chunk" up the request's for very large uploads. Feel free to change "chunk_size" to something very large (or even the size of the input string) to make it all go in one shot.

     

     

    To answer why your code always appends the data to the file, I don't see where your first write is using the FILE_FIRST or FILE_FIRST_OR_LAST chain type. This will tell the server to truncate the existing file before the write of the data. If you have FILE_MIDDLE or FILE_LAST as the first write, it will append to the file.

     

     

    If you want a simple function that takes input as a string and uploads the entire string in one shot, this should do it for you (making use of the above conversion method)

     

     

    void uploadStringToFile(String target_file, String contents)
    {
      iControl.SystemConfigSyncFileTransferContext ctx = new iControl.SystemConfigSyncFileTransferContext();
      ctx.file_data = StrToByteArray(contents);
      ctx.chain_type = iControl.CommonFileChainType.FILE_FIRST_AND_LAST;
      m_interfaces.SystemConfigSync.upload_file(target_file, ctx);
    }

     

     

    Make sense?

     

     

    -Joe
  • Hi,

     

     

    It makes perfect sense! Thanks

     

     

    i made a mistake by putting FILE_FIRST_AND_LAST instead of FILE_FIRST ><

     

     

    and thanks for the function to translate a string in byte[].

     

     

    I guess i'll need to check all those translation type!

     

     

    Thanks again

     

  • Take a look at the PerlConfigSync sample in the iControl CodeShare. That may point you in the right direction.

     

     

    http://devcentral.f5.com/wiki/iControl.PerlConfigSync.ashx

     

     

    -Joe