Beispiel #1
0
        /// <summary>
        /// Creates or updates file in the remote storage.
        /// </summary>
        /// <param name="remoteStoragePath">Path of the file to be created or updated in the remote storage.</param>
        /// <param name="newInfo">New information about the file, such as modification date, attributes, custom data, etc.</param>
        /// <param name="mode">Specifies if a new file should be created or existing file should be updated.</param>
        /// <param name="newContentStream">New file content or null if the file content is not modified.</param>
        /// <param name="eTagOld">The ETag to be sent to the remote storage as part of the update request to make sure the content is not overwritten.</param>
        /// <param name="lockInfo">Information about the lock. Null if the item is not locked.</param>
        /// <returns>The new ETag returned from the remote storage.</returns>
        protected async Task <string> CreateOrUpdateFileAsync(
            string remoteStoragePath, IFileMetadata newInfo, FileMode mode, Stream newContentStream = null, string eTagOld = null, ServerLockInfo lockInfo = null)
        {
            FileInfo remoteStorageItem = new FileInfo(remoteStoragePath);

            try
            {
                Program.VirtualDrive.RemoteStorageMonitor.Enabled = false; // Disable RemoteStorageMonitor to avoid circular calls.

                // If another thread is trying to sync the same file, this call will fail in other threads.
                // In your implementation you must lock your remote storage file, or block it for reading and writing by other means.
                await using (FileStream remoteStorageStream = remoteStorageItem.Open(mode, FileAccess.Write, FileShare.None))
                {
                    string userFileSystemPath = Mapping.ReverseMapPath(remoteStoragePath);
                    if (mode == FileMode.Open)
                    {
                        // Verify that the item in the remote storage is not modified since it was downloaded to the user file system.
                        // In your real-life application you will send the ETag to the server as part of the update request.
                        FileSystemItemMetadataExt itemInfo = Mapping.GetUserFileSysteItemMetadata(remoteStorageItem);
                        if (!(await VirtualDrive.GetETagManager(userFileSystemPath).ETagEqualsAsync(itemInfo)))
                        {
                            throw new ConflictException(Modified.Server, "Item is modified in the remote storage, ETags not equal.");
                        }
                    }

                    // Update ETag/LastWriteTime in user file system, so the synchronyzation or remote storage monitor would not start the new update.
                    // This is only required to avoid circular updates because of the simplicity of this sample.
                    // In your real-life application you will receive a new ETag from the server in the update response
                    // and return it from this method.
                    string eTagNew = newInfo.LastWriteTime.ToUniversalTime().ToString("o");
                    await VirtualDrive.GetETagManager(userFileSystemPath).SetETagAsync(eTagNew);

                    // Update remote storage file content.
                    if (newContentStream != null)
                    {
                        await newContentStream.CopyToAsync(remoteStorageStream);

                        remoteStorageStream.SetLength(newContentStream.Length);
                    }

                    // Update remote storage file basic info.
                    WindowsFileSystemItem.SetFileInformation(
                        remoteStorageStream.SafeFileHandle,
                        newInfo.Attributes,
                        newInfo.CreationTime,
                        newInfo.LastWriteTime,
                        newInfo.LastAccessTime,
                        newInfo.LastWriteTime);

                    return(eTagNew);
                }
            }
            finally
            {
                Program.VirtualDrive.RemoteStorageMonitor.Enabled = true;
            }
        }
        private async Task CreateOrUpdateFileAsync(string userFileSystemPath, bool create)
        {
            try
            {
                Program.RemoteStorageMonitorInstance.Enabled = false; // Disable RemoteStorageMonitor to avoid circular calls.

                FileInfo userFileSystemFile = new FileInfo(userFileSystemPath);
                FileInfo remoteStorageFile  = new FileInfo(remoteStoragePath);

                FileMode fileMode = create ? FileMode.CreateNew : FileMode.Open;


                await using (FileStream userFileSystemStream = userFileSystemFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    // If another thread is trying to sync the same file, this call will fail in other threads.
                    // In your implemntation you must lock your remote storage file, or block it for reading and writing by other means.
                    await using (FileStream remoteStorageStream = remoteStorageFile.Open(fileMode, FileAccess.Write, FileShare.None))
                    {
                        userFileSystemFile.Refresh(); // Ensures LastWriteTimeUtc is in sync with file content after Open() was called.

                        // Update ETag/LastWriteTime in user file system, so the synchronyzation or remote storage monitor would not start the new update.
                        byte[] customData = BitConverter.GetBytes(userFileSystemFile.LastWriteTime.ToBinary());
                        PlaceholderItem.SetCustomData(userFileSystemStream.SafeFileHandle, customData);

                        // Update remote storage file content.
                        await userFileSystemStream.CopyToAsync(remoteStorageStream);

                        remoteStorageStream.SetLength(userFileSystemStream.Length);

                        // Update remote storage file basic info.
                        WindowsFileSystemItem.SetFileInformation(remoteStorageStream.SafeFileHandle,
                                                                 userFileSystemFile.Attributes & (FileAttributes) ~FileAttributesExt.Pinned, // Remove Pinned flag.
                                                                 userFileSystemFile.CreationTimeUtc,
                                                                 userFileSystemFile.LastWriteTimeUtc,
                                                                 userFileSystemFile.LastAccessTimeUtc,
                                                                 userFileSystemFile.LastWriteTimeUtc);

                        // If you are using ETags, here you will also send to the remote storage a new file ETag.

                        PlaceholderItem.SetInSync(userFileSystemStream.SafeFileHandle, true);
                    }
                }
            }
            finally
            {
                Program.RemoteStorageMonitorInstance.Enabled = true;
            }
        }