Receive data from value storage 1s 8.3. Limitations when working with the Web client
Almost any information can be stored in a value store, e.g.
... pictures (photos):
// in this place it displays everything... Form Elements.PictureField1.Picture = Storage.Get(); CurrentImage.Write();
...spreadsheet document:
TabDoc=New TabularDocument; TabDoc.Output(FormElements.TabularDocumentField1); Storage=NewValueStorage(TabDoc); Write();
End of Procedure
Procedure RestoreFromStoragePress(Element)
TabDoc=Storage.Get(); If TabDoc<>Undefined ThenFormElements.TabularDocumentField1.Output(TabDoc); endIf;
End of Procedure
...arbitrary files (binary data):
Eight supports compression of data placed in storage:
... external processing and reporting:
CompressionRate = NewDataCompression(9); //9 maximum PropsStorageType = New StorageValues(New BinaryData("c:\reports\report.epf", Compression Rate));
End of Procedure
Procedure StartProcessingFromStorage(PropsStorageType)
TemporaryFileName = TemporaryFileDirectory()+"report.epf"; BinaryData = PropsStorageType.Get(); BinaryData.Write(TemporaryFileName); ExternalProcessing = ExternalProcessing.Create(TemporaryFileName); ExternalProcessing.GetForm().Open();
End of Procedure
Working with storage
If it was Binary Data, then it can be restored from the value store using the Get method and written to a file using the Write() method.
BinaryData = Storage.Get();
BinaryData = Storage;
endIf; BinaryData.Write(FileName);
If it was, for example, a Word document (doc file, or other registered file type), then it can be opened like this:
To clear a field of type Value Storage, you need to assign it Undefined:
Working with files and pictures in the built-in language 1C:Enterprise 8
Purpose
The managed application implements a new mechanism for working with files. It provides file exchange between the infobase and the client application. The peculiarity of this mechanism is that it is designed for use in a thin client and a Web client and is designed taking into account the restrictions on working with files imposed by Web browsers.
The mechanism is a set of methods that can be used to place data stored locally on the user's computer in a temporary storage of the information base, transfer this information from the temporary storage to the database, and receive it back to the user's computer. The most common application problems solved by this mechanism are the storage of accompanying information, for example, images of goods, documents related to contracts, etc.
Method Scope
Temporary storage
Temporary storage is a specialized area of the information base in which binary data can be placed. The main purpose is the temporary storage of information during client-server interaction before it is transferred to the database.
The need for temporary storage arises because the web browser operating model requires that the user-selected file be transferred directly to the server without the possibility of storing it on the client. When a file is transferred, it is placed in temporary storage and can then be used when writing an object to the database.
The most typical application task solved by temporary storage is providing access to files or pictures before the object is recorded in the information base, for example, in the form of an element.
A file or binary data placed in storage is identified by a unique address, which can later be used in write, read, or delete operations. This address is given by methods for writing a file to temporary storage. A separate method in the built-in language allows you to determine whether the passed address is an address pointing to data in temporary storage.
Information base
The mechanism allows you to access binary data stored in attributes of the Value Storage type.
As in the case of temporary storage, access to information is possible through a special address. You can get it through a special method by passing a link to an object or an information register entry key, and the name of the attribute. In the case of a tabular part, it is additionally required to transfer the row index of the tabular part.
Methods for working with files have limitations when working with infobase details. For them, unlike temporary storage, only reading information is available, but not writing or deleting it.
Description of methods for working with files
Saving data to temporary storage
The most typical scenario for using this mechanism involves initially placing user data in temporary storage. There are two methods for this: PlaceFile() and PlaceFileInTemporaryStorage().
The first method, PlaceFile(), places a file from the local file system into temporary storage. The method can accept a target address in storage. If it is not defined or is an empty string, then a new file will be created and the method will return its address through the corresponding parameter.
If the parameter that determines the interactive mode of operation is True, then the method will display a standard file selection dialog box in which you can select a file to place in storage. In this case, the method will also return the address of the selected file.
As a result, the method returns False if the user interactively refused to perform an operation in the file selection dialog. The method is only available on the client.
The second method, PlaceFileInTemporaryStorage(), is similar to the previous one, except that it is available on the server, and the data to be written to temporary storage is represented not as a path in the file system, but as a variable of type BinaryData. Likewise, if no target address is specified, a new file is created in the storage. Its address is returned as the result of the function.
Retrieving a file from temporary storage
When writing an object to the infobase, you may need to extract data from temporary storage and place it, for example, in an attribute. There is a corresponding server method for this - GetFileFromTemporaryStorage(). This method retrieves data from temporary storage and returns it as a result. To do this, you need to specify the address in temporary storage. This address is returned by the above-described methods PlaceFile() and PlaceFileInTemporaryStorage() if they are executed successfully.
Deleting a file from temporary storage
After the data is saved in the details, the file in temporary storage can be deleted. For this purpose, there is a method DeleteFileFromTemporaryStorage(), which deletes a file from temporary storage. The method takes as a parameter the address of a file in temporary storage. Available on the server.
Checking the address for temporary storage
The file address can indicate both temporary storage and details in the infobase. To check its type, there is a method This isTemporaryStorageAddress().
It checks that the passed address is an address pointing to the store. Returns True if the address points to temporary storage. The method is available on the server.
Receiving the props address
After the data is placed in the details in the infobase, you may need to access it using file methods.
But before you receive data, for example from a property, you need to get the address of this property. For this purpose, there is a method GetFileAddressInInformationBase().
Its purpose is to return the file address in the infobase according to the original parameters. To do this, you need to pass the object key (this can be either a link to the object or an information register entry key) and the name of the attribute. If you need to get the address of a file stored in a tabular part attribute, before the attribute name in the parameter specifying the attribute name, you need to add the name of the tabular part and a dot “.”. The method is available on both the client and the server.
Retrieving a file from the infobase
The GetFile() method receives a file from the infobase and saves it to the user's local file system. The first parameter specifies the address of the file in the props or temporary file storage. The second parameter specifies the destination location of the resulting file. In non-interactive mode, you must specify the path. In interactive mode, the parameter is optional.
By default, the method is executed in interactive mode, that is, the last parameter is True. This means that a dialog box is displayed in which you can specify an action with the received file: run it or save it to a user-specified location. If interactive mode is active and the Target disk file path parameter is not specified, the file open operation is not available. Returns a boolean value. False means the user chose to cancel the operation in the interactive save file dialog box.
Example of using file methods
Variable SelectedName; VariableTemporaryStorageAddress; If PutFile(TemporaryStorageAddress, SelectedName, True) Then Object.FileName = SelectedName; PlaceObjectFile(TemporaryStorageAddress); endIf;
End of Procedure
// Copying a file from temporary storage to a directory // attribute, recording an object, deleting a file from temporary // storage &On the Server Procedure Place Object File (Temporary Storage Address)
Directory Element = Form AttributesValue("Object"); BinaryData = GetFileFromTemporaryStorage(TemporaryStorageAddress); Directory Element.File Data = NewValueStorage(BinaryData); FilePathOnDisk = New File(DirectoryItem.FileName); Directory Item.FileName = FilePathOnDisk.Name; Directory element.Write(); Modified = False; DeleteFileFromTemporaryStorage(TemporaryStorageAddress); ValueВFormAttributes(Directory Element, "Object");
End of Procedure
// Reading a file from the props and saving it // on the local disk in interactive mode &On the Client Procedure ReadFileAndSaveToDisk()
Address = GetFileAddressInInformationBase(Object.Link, "FileData"); GetFile(Address, Object.FileName, True);
End of Procedure
Support for addresses in the picture field
The Picture Field control supports displaying a picture specified by the address of a file in temporary storage or in a database.
To do this, you must set a string type attribute in the Data property of the form element. The value of this attribute will be interpreted as the address of the picture.
Example
PlaceFile(PictureAddress,True)
Picture.Data = AddressPictures
Limitations when working with the Web client
The operation of the described mechanism when using the Web client has some limitations. These restrictions are related to the browser's security model. So, for example, the client cannot independently save a file to the local file system, that is, only the interactive version of the client methods PlaceFile() and GetFile() is available. An exception is thrown when attempting to use non-interactive mode. The dialog boxes that appear interactively are specific to your browser type.
Features when working with Value Storage on the Client
Problem:
When a Document has an attribute of the Value Storage type in the tabular section, it slows down the opening of the document form if this attribute contains large data.
Supposed reason:
Perhaps, when opening a form, it is not the link to the data located in the Value Store that is sent to the client, but the data itself.
Solution
- In the properties of the form's table attribute there is a flag "Always use". If it is set, the contents of the field are always transferred between the server and the client - for example, when opening a form. This flag must be disabled, but this must be taken into account in the code, since by default there will be no value for this field on the client. An example can be found in 1C:Archive.
It's even better to use temporary storage to transfer files between client and server.
We have a directory “Products”, in the “Data” attribute of which information is stored in the form of binary data. The attribute itself has the value type "Value Storage". The following screenshot shows the directory metadata structure.
To attach an arbitrary file from disk in the form of an element, the "AttachFile" command has been implemented. Its program code is presented in the following listing:
& On the Client Procedure AttachFile(Command) // Command handler on the client. File selection // Dialog for selecting a file from disk Mode = FileSelectionDialogMode. Opening; OpenFileDialog = NewFileSelectDialog(Mode); OpenFile Dialog. FullFileName = " " ; OpenFile Dialog. MultipleSelect = False ; OpenFile Dialog. Title = "Select files" ; If FileOpenDialog. Select() Then FilePath = FileOpenDialog. FullFileName; // Receive binary file data BinaryData = new BinaryData(PathToFile) ; // Transfer binary data to the server AttachFileServer(BinaryData) ; Otherwise Text = "ru = " " File (s) not selected!" " ; en =" " File (s) not selected!" " " ; Warning(NStr(Text) ) ; EndIf ; EndProcedure & OnServer Procedure AttachFileServer(BinaryData) // Handler on the server for recording a file in the information security // Transform the form object into a reference object ObjectCurrent = FormAttributesValue("Object" ) ; // Assign a new value to the "Data" attribute ObjectCurrent. Data = NewValueStorage(BinaryData) ; // Save changes ObjectCurrent. Write() ; End of ProcedureIf we describe the algorithm in general terms, then first a file is selected from the disk on the client. The resulting binary file data is sent to the server, where it is recorded in the information base, namely in the “Data” attribute of the current directory element.
In principle, everything works. When opening an element, we can read this data as needed. If, for example, an image is saved in the attribute, then we can get it and display it in the form field. This solution has a place, but in most tasks it is not optimal to use attributes with the value type “Value Storage” in directories and documents. And that's why...
Performance Impact
Let's run some performance tests. The tests will use two elements of the "Products" directory, with and without an attached file. The size of the attached file is 5 megabytes.
All tests are performed using the "GetElement" processing in the test configuration. You can download this configuration from the link at the end of the article.
Let's measure the time it takes to open items in the "Products" directory. To open an element, the global context method "OpenValue()" is used, which is passed a reference to the element as a parameter. Let's measure the opening time using a standard performance measurement tool. The results are presented in the following screenshot:
As we can see, the time it takes to open an element with an attached file is 10 times longer! Let's do another test. Let's execute the "GetObject()" method to reference the product catalog element. You can see the test result in the following screenshot.
The difference is quite significant. Receiving an element without an attached file is 194 times faster!
This happens because the “GetObject()” method receives all the data from the details of the directory element by reference. Accordingly, the method receives the values of not only the “Code” and “Name” attributes, but also the value of the “Data” attribute. If it stores binary data of 5 megabytes in size (as in our example), then when the object is received, this data is placed in RAM (like other details) and then transferred to the client side. It is the receipt of data from this attribute that increases the time for obtaining the element object. If a thin communication channel is used, then the opening time will increase even more significantly due to the transfer of a large amount of information over the network.
Note: when executing the "OpenValue()" method, the directory element object is also first obtained, and then transformed into a form object and passed to the client (for managed forms). That is, when an element is opened by reference, the object is also retrieved.
Let's conduct a final test on the time it takes to open and write a directory item with and without an attached file. The result is shown in the following screenshot.
Natural result. The time to receive and then write for a directory item with an attached file turned out to be ~19 times longer. As mentioned above, when receiving an object, the values of all its details are obtained, including the “Data” attribute in which 5 megabytes of information are stored. When an element is written, this amount of data is again written to the infobase. Consequently, storing data in a directory attribute (or document) with the “Value Storage” type negatively affects performance both when retrieving an object and when placing it in the infobase.
What is the most correct way to solve the problem of storing data for information base objects?
Correct solution
If we look at the implementation of this mechanism in typical configurations, we will see that for objects additional information is stored in a separate information register table. This is, for example, what the attachment file mechanism looks like in a standard configuration of “Trade Management” version 11.
The "Nomenclature" directory is the owner for the "NomenclatureAttachedFiles" directory. This, in turn, is associated with the AttachedFiles information register, the AttachedFile dimension of which refers to its element. Thus, data attached to information base objects is actually stored in the information register table, the operation of which is practically not affected by the amount of data stored in the resource. The intermediate directory "Nomenclature of Attached Files" is necessary to store additional information for the attached file, as well as to support access to the attached file by reference.
All of the above once again confirms the enormous performance impact of a properly designed configuration metadata structure.
Test configuration with an example from the article: LINK .
Platform 1C:Enterprise provides a lot of possibilities for storing data of various types.
But often these opportunities are not enough. And then a special object comes to our aid - StorageValues. This object allows you to store in a special format both standard 1C:Enterprise objects, for example, a table of values, and non-standard ones for which a type is not provided in the platform. Non-standard types may include files. For example, using a value store in a 1C database, you can store photographs of employees, scans of documents, external processing, etc. The advantage here is that all these objects are stored in the database itself. Accordingly, when deploying a new database from a backup copy, all these objects will also be present in the new database. On the other hand, if you store large files in the database, this can significantly increase its volume and negatively affect its performance. Therefore, a reasonable balance must be maintained here.
Let's look at working with a value store using an example. Let's create a special directory in the configurator - let's call it ExternalObjects, and in turn we will create the requisites for the directory An object with type StorageValues
And now we can create elements in this directory, and in props An object Each element is written to a file.
Working with a value store is very simple. If we look at the syntax helper, we will see that this object has only one method and one constructor.
Now, for demonstration, let’s write the simplest code that will write a file to the props An object a previously created directory element, and then read this file from the props and write it to disk, but under a different name.
&On the Server Procedure LoadUnloadFile(Directory Element)Directory Object =Directory Element. GetObject() ; //Place the image in the value store LabelDownload = New Image("g:\musor\favicon.ico" ) NewValueStorage; //Write a directory element Directory object. DirectoryObject object. Write() ; //Upload the image from the value store to a file FileName = "g:\musor\favicon_1.ico" ; LabelUpload = Directory Object. An object. Get() ; LabelUpload. Write(FileName) ; End of ProcedureAnd a few explanations for the code.
- The object is placed into the store directly when the store is created using the constructor.
To store other types of files other than images in storage, you can use the object BinaryData. Purely theoretically, you can even store directory elements, documents, etc. in the value store. But in practice this doesn't make any sense. But it is sometimes possible to use a value store to store a table of values, a tree of values, and other universal collections.