Convert from System.IO.FileStream to InStream

wakestar
Member Posts: 207
Hi there
I'm trying to load the FileStream of a file on the client with System.IO.File.OpenRead() into a InStream but I get the error:
Unable to convert from Runtime.NavDotNet to Nav.Runtime.NavInStream
I tried with different .NET Stream types and with COPYSTREAM but no luck so far... :-(
What am I missing here? Does anyone have a working example?
I'm trying to load the FileStream of a file on the client with System.IO.File.OpenRead() into a InStream but I get the error:
Unable to convert from Runtime.NavDotNet to Nav.Runtime.NavInStream
FileStream := ClientFile.OpenRead(ClientFilePath); InStr := FileStream;
I tried with different .NET Stream types and with COPYSTREAM but no luck so far... :-(
What am I missing here? Does anyone have a working example?
0
Best Answers
-
Hi,
May i know why you need to pass FileStream to InStream.
"Reads a specified number of bytes from an InStream object. Data is read in binary format.". So, You no need to use Instream if you use the FileStream. You can pass FileStream value to other OutStream or other stream.Name DataType Subtype Length dnetFileStream DotNet System.IO.FileStream.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' dnetFileMode DotNet System.IO.FileMode.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' dnetStream DotNet System.IO.Stream.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' NavInStream InStream NavOutStream OutStream NavOutStreamFile OutStream NavFileSource File NavFileDes File recTempBlob Record TempBlob
recTempBlob.Blob.CREATEOUTSTREAM(NavOutStream); dnetFileMode := dnetFileMode.Open; dnetFileStream := dnetFileStream.FileStream('c:\temp\source.txt',dnetFileMode); dnetStream := dnetFileStream; dnetStream.CopyTo(NavOutStream); dnetStream.Close; dnetFileStream.Close; //Making InStream (copy stream from .Net Stream) recTempBlob.Blob.CREATEINSTREAM(NavInStream); //Write File using Instream NavFileDes.CREATE('c:\temp\destination.txt'); NavFileDes.CREATEOUTSTREAM(NavOutStreamFile); COPYSTREAM(NavOutStreamFile,NavInStream); NavFileDes.CLOSE; MESSAGE('Done ....!'); //Using Instream and Outstream NavFileSource.OPEN('c:\temp\source.txt'); NavFileSource.CREATEINSTREAM(NavInStream); NavFileDes.CREATE('c:\temp\destination.txt'); NavFileDes.CREATEOUTSTREAM(NavOutStreamFile); COPYSTREAM(NavOutStreamFile,NavInStream); NavFileSource.CLOSE(); NavFileDes.CLOSE(); MESSAGE('Done ....!');
Regards,Make Simple & Easy5 -
Try to use this as per your requirement. This is read the client file and create the file server
Name DataType Subtype Length dnetFileStreamClient DotNet System.IO.FileStream.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' dnetFileModeClient DotNet System.IO.FileMode.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' dnetMemoryStreamClient DotNet System.IO.MemoryStream.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' dnetArrayClient DotNet System.Array.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' dnetMemoryStreamServer DotNet System.IO.MemoryStream.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' NavOutStreamFile OutStream NavFileDes File
dnetFileModeClient := dnetFileModeClient.Open; dnetFileStreamClient := dnetFileStreamClient.FileStream('C:\Temp\source.txt',dnetFileModeClient); dnetMemoryStreamClient := dnetMemoryStreamClient.MemoryStream; dnetFileStreamClient.CopyTo(dnetMemoryStreamClient); dnetArrayClient := dnetMemoryStreamClient.GetBuffer; dnetMemoryStreamServer := dnetMemoryStreamServer.MemoryStream(dnetArrayClient); //Can skip this line and above line if you use below comment code. //dnetMemoryStreamServer := dnetMemoryStreamServer.MemoryStream(dnetMemoryStreamClient.GetBuffer); //Memory Stream Byte to make Server Memory Stream //Write File using Server Memory Stream NavFileDes.CREATE('C:\Temp\destination.txt'); NavFileDes.CREATEOUTSTREAM(NavOutStreamFile); dnetMemoryStreamServer.CopyTo(NavOutStreamFile); NavFileDes.CLOSE; dnetMemoryStreamServer.Close; dnetMemoryStreamClient.Close; dnetFileStreamClient.Close; MESSAGE('File is created on your server...!');
Note : dnetxxxClient => RunOnClient=Yes, dnetxxxServer => RunOnClient=No
Regards,Make Simple & Easy5
Answers
-
Hi,
FileStream to MemoryStream(.Net) and then MemoryStream to Your Nav Stream.
RegardsMake Simple & Easy0 -
Hi
I tried that.. same error.
Do you have a working example code?0 -
Hi,
Now I far from PC. I will update back to you if noon ans. Sorry for my this reply.
Regards,Make Simple & Easy0 -
no problem0
-
Hi,
May i know why you need to pass FileStream to InStream.
"Reads a specified number of bytes from an InStream object. Data is read in binary format.". So, You no need to use Instream if you use the FileStream. You can pass FileStream value to other OutStream or other stream.Name DataType Subtype Length dnetFileStream DotNet System.IO.FileStream.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' dnetFileMode DotNet System.IO.FileMode.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' dnetStream DotNet System.IO.Stream.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' NavInStream InStream NavOutStream OutStream NavOutStreamFile OutStream NavFileSource File NavFileDes File recTempBlob Record TempBlob
recTempBlob.Blob.CREATEOUTSTREAM(NavOutStream); dnetFileMode := dnetFileMode.Open; dnetFileStream := dnetFileStream.FileStream('c:\temp\source.txt',dnetFileMode); dnetStream := dnetFileStream; dnetStream.CopyTo(NavOutStream); dnetStream.Close; dnetFileStream.Close; //Making InStream (copy stream from .Net Stream) recTempBlob.Blob.CREATEINSTREAM(NavInStream); //Write File using Instream NavFileDes.CREATE('c:\temp\destination.txt'); NavFileDes.CREATEOUTSTREAM(NavOutStreamFile); COPYSTREAM(NavOutStreamFile,NavInStream); NavFileDes.CLOSE; MESSAGE('Done ....!'); //Using Instream and Outstream NavFileSource.OPEN('c:\temp\source.txt'); NavFileSource.CREATEINSTREAM(NavInStream); NavFileDes.CREATE('c:\temp\destination.txt'); NavFileDes.CREATEOUTSTREAM(NavOutStreamFile); COPYSTREAM(NavOutStreamFile,NavInStream); NavFileSource.CLOSE(); NavFileDes.CLOSE(); MESSAGE('Done ....!');
Regards,Make Simple & Easy5 -
Nice examples, what were you global variables?0
-
Hi,
Update with Global variables.
Regards,Make Simple & Easy0 -
Thx0
-
Hi yukon
Thanks so far for the example!May i know why you need to pass FileStream to InStream.
At the moment I'm playing around with Vjeko's DLL hell solution and try to reuse existing functions.
If you look at the function InstallAssembly you'll notice that the first parameter is InStream.
And in my case I'm implementing a new function which let's you pick an entire folder on the client and all of the *.dll files should be imported at once to the DotNet Assembly table. And I actually managed to get this working by uploading the files first to the service tier and then import them from there.FileMgt.UploadFileSilent(ClientFilePath,ServerFilePath); FileMgt.BLOBImportFromServerFile(TempBlob,ServerFilePath); TempBlob.Blob.CREATEINSTREAM(InStr); InstallDotNetAssembly(InStr,Asm,'');
BUT ... I then thought maybe I could use Streams to transfer from the client directly to the server without going through Upload and temporary folder. So in my case I would like to have all of the .NET assemblies defined as "RunOnClient=Yes" ...
but now I get this:Microsoft Dynamics NAV
This message is for C/AL programmers: Client/server communication, cannot serialize an instance of the following .NET Framework object: assembly Microsoft.Dynamics.Nav.Ncl, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, type Microsoft.Dynamics.Nav.Runtime.NavBLOB+InternalStream.
OK
So that basically means that we cannot serialize this stuff and your example works as long as the file is already on the service tier... correct?0 -
Hi,
I haven't check Vjeko's post. So i cannot tell you what can be amend on your code base on your requirement. You cannot pass the Client Side Variable to Server side or Server Side Var to Client. You are trying to pass Client Side variable (RunOnClient=Yes) to Server side variable. This post is same as your error. https://community.dynamics.com/nav/f/34/t/186866
Regards,Make Simple & Easy0 -
Thanks for confirming that! Yes it's a bummer and I guess the solution is to use base64 strings. - Which is what I'll try next :-)0
-
so why can't you just use the "..through Upload and temporary folder.." to get the file at the client location?0
-
I could and it works. - But I'm trying to avoid the *files-pushing-around-between-temp-folders*0
-
Try to use this as per your requirement. This is read the client file and create the file server
Name DataType Subtype Length dnetFileStreamClient DotNet System.IO.FileStream.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' dnetFileModeClient DotNet System.IO.FileMode.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' dnetMemoryStreamClient DotNet System.IO.MemoryStream.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' dnetArrayClient DotNet System.Array.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' dnetMemoryStreamServer DotNet System.IO.MemoryStream.'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' NavOutStreamFile OutStream NavFileDes File
dnetFileModeClient := dnetFileModeClient.Open; dnetFileStreamClient := dnetFileStreamClient.FileStream('C:\Temp\source.txt',dnetFileModeClient); dnetMemoryStreamClient := dnetMemoryStreamClient.MemoryStream; dnetFileStreamClient.CopyTo(dnetMemoryStreamClient); dnetArrayClient := dnetMemoryStreamClient.GetBuffer; dnetMemoryStreamServer := dnetMemoryStreamServer.MemoryStream(dnetArrayClient); //Can skip this line and above line if you use below comment code. //dnetMemoryStreamServer := dnetMemoryStreamServer.MemoryStream(dnetMemoryStreamClient.GetBuffer); //Memory Stream Byte to make Server Memory Stream //Write File using Server Memory Stream NavFileDes.CREATE('C:\Temp\destination.txt'); NavFileDes.CREATEOUTSTREAM(NavOutStreamFile); dnetMemoryStreamServer.CopyTo(NavOutStreamFile); NavFileDes.CLOSE; dnetMemoryStreamServer.Close; dnetMemoryStreamClient.Close; dnetFileStreamClient.Close; MESSAGE('File is created on your server...!');
Note : dnetxxxClient => RunOnClient=Yes, dnetxxxServer => RunOnClient=No
Regards,Make Simple & Easy5 -
Hi yukon,
I like your code to the point where you have it in the dnetMemoryStreamServer.//dnetMemoryStreamServer := dnetMemoryStreamServer.MemoryStream(dnetMemoryStreamClient.GetBuffer); //Memory Stream Byte to make Server Memory Stream
But I don't want to save the file on the server at all. It should go from MemoryStreamServer to directly into the InStream (BLOB-Field)
btw. I appreciate your input!0 -
But I don't want to save the file on the server at all. It should go from MemoryStreamServer to directly into the InStream (BLOB-Field)
I show you the code is how to pass Client Memory value to Server Memory if RunOnClient is different between two variable (Memory Stream). You can save to InStream(Blob-field) after you get MemoryStreamServer. For your requirement you may need to combine two example.//dnetMemoryStreamServer := dnetMemoryStreamServer.MemoryStream(dnetMemoryStreamClient.GetBuffer); //Memory Stream Byte to make Server Memory Stream
I like to use above code because i can be reduce the variable (dnetArrayClient) and code. And then MemoryStream constructor allow me to do from byte.
Regards,Make Simple & Easy1 -
Ah OK, I see what you mean.
I'll have to do some testing and tuning but looks good so far.
I like the solution because it's not doing any roundtrips through the temporary folders.
BIG THANKS0 -
its a bit hard to understand for me...:) so in pseudo steps what you are trying to do:
1.
your opening a file on the client into memory
2.
and save it to a file on the server
(but no use of temp files)
0 -
Almost :-)
1. correct
2. not to file but to Temp.Blob field on a table.
So in short: Get the file from the client and save it directly into some Blob field of a table without any temp files created anywhere ...
The standard microsoft approach does round trips and pollutes the temporary folders before you have the file in your database. - Not a great solution IMHO.
0 -
ok, thx for clearing this up. If you can, please share the working code you used. Or publish in tips0
-
as soon as I'm really sure what I'm doing ;-)0
-
I did some testing and I ran into OutOfMemory-Exception when importing around 15 files each 10mb.
I guess the problem is described here: http://stackoverflow.com/questions/13053739/when-is-getbuffer-on-memorystream-ever-useful
But for importing a bunch of smaller files (dlls) I haven't seen any issues yet.
The code is prototypical ... use it at own risk :-)
https://gist.github.com/wakestar/4200f18e8a71584cb9b90 -
I was looking to this download http://mibuso.com/downloads/nav-object-renumbering-tool
I thought the source was related and maybe of use..0
Categories
- All Categories
- 73 General
- 73 Announcements
- 66.6K Microsoft Dynamics NAV
- 18.7K NAV Three Tier
- 38.4K NAV/Navision Classic Client
- 3.6K Navision Attain
- 2.4K Navision Financials
- 116 Navision DOS
- 851 Navision e-Commerce
- 1K NAV Tips & Tricks
- 772 NAV Dutch speaking only
- 617 NAV Courses, Exams & Certification
- 2K Microsoft Dynamics-Other
- 1.5K Dynamics AX
- 320 Dynamics CRM
- 111 Dynamics GP
- 10 Dynamics SL
- 1.5K Other
- 990 SQL General
- 383 SQL Performance
- 34 SQL Tips & Tricks
- 35 Design Patterns (General & Best Practices)
- 1 Architectural Patterns
- 10 Design Patterns
- 5 Implementation Patterns
- 53 3rd Party Products, Services & Events
- 1.6K General
- 1.1K General Chat
- 1.6K Website
- 83 Testing
- 1.2K Download section
- 23 How Tos section
- 252 Feedback
- 12 NAV TechDays 2013 Sessions
- 13 NAV TechDays 2012 Sessions