/// <summary> /// Copies an existing file to a new file. Overwriting a file of the same name is allowed. /// </summary> /// <param name="sourceFileName">Path to source file.</param> /// <param name="destFileName">Path to destination file.</param> /// <param name="overwrite">If destination file should be overwritten.</param> public override void Copy(string sourceFileName, string destFileName, bool overwrite) { if (!this.Exists(sourceFileName)) { throw GetFileNotFoundException(sourceFileName); } bool destExists = CMS.IO.File.Exists(destFileName); if (destExists && !overwrite) { return; } if (!StorageHelper.IsSameStorageProvider(sourceFileName, destFileName)) { StorageHelper.CopyFileAcrossProviders(sourceFileName, destFileName); } else { IS3ObjectInfo sourceInfo = S3ObjectFactory.GetInfo(sourceFileName); IS3ObjectInfo destInfo = S3ObjectFactory.GetInfo(destFileName); if (destExists) { Provider.DeleteObject(destInfo); } if (Provider.ObjectExists(sourceInfo)) { Provider.CopyObjects(sourceInfo, destInfo); } else { Provider.PutFileToObject(destInfo, sourceFileName); } IS3ObjectInfo destDirectoryInfo = S3ObjectFactory.GetInfo(CMS.IO.Path.GetDirectoryName(destFileName)); destDirectoryInfo.Key = $"{destDirectoryInfo.Key}/"; if (!Provider.ObjectExists(destDirectoryInfo)) { Provider.CreateEmptyObject(destDirectoryInfo); } var now = DateTime.Now; destDirectoryInfo.SetMetadata(S3ObjectInfoProvider.LAST_WRITE_TIME, S3ObjectInfoProvider.GetDateTimeString(now)); destInfo.SetMetadata(S3ObjectInfoProvider.LAST_WRITE_TIME, S3ObjectInfoProvider.GetDateTimeString(now), false); destInfo.SetMetadata(S3ObjectInfoProvider.CREATION_TIME, S3ObjectInfoProvider.GetDateTimeString(now)); } }
/// <summary>Deletes object from Amazon S3 storage.</summary> /// <param name="obj">Object info.</param> public void DeleteObject(IS3ObjectInfo obj) { this.S3Client.DeleteObject(new DeleteObjectRequest() { BucketName = obj.BucketName, Key = obj.Key }); obj.DeleteMetadataFile(); FileDebug.LogFileOperation(PathHelper.GetPathFromObjectKey(obj.Key, true), nameof(DeleteObject), "Custom Amazon"); RemoveRequestCache(obj.Key); try { RemoveFromTemp(obj); RemoveFromCache(obj); } catch (IOException) { } }
/// <summary>Puts text to Amazon S3 storage object.</summary> /// <param name="obj">Object info.</param> /// <param name="content">Content to add.</param> public void PutTextToObject(IS3ObjectInfo obj, string content) { if (obj.IsLocked) { throw new Exception($"[IS3ObjectInfoProvider.PutTextToObject]: Couldn't upload object {obj.Key} because it is used by another process."); } string pathFromObjectKey = PathHelper.GetPathFromObjectKey(obj.Key, true); obj.Lock(); PutObjectRequest putRequest = CreatePutRequest(obj.Key, GetBucketName(pathFromObjectKey)); putRequest.ContentBody = content; PutObjectResponse response = this.S3Client.PutObject(putRequest); this.SetS3ObjectMetadaFromResponse(obj, response, 0L); FileDebug.LogFileOperation(PathHelper.GetPathFromObjectKey(obj.Key, true), nameof(PutTextToObject), "Custom Amazon"); obj.UnLock(); RemoveRequestCache(obj.Key); }
/// <summary> /// Opens a text file, reads all lines of the file, and then closes the file. /// </summary> /// <param name="path">Path to file.</param> public override string ReadAllText(string path) { if (!this.Exists(path)) { throw GetFileNotFoundException(path); } IS3ObjectInfo info = S3ObjectFactory.GetInfo(path); if (!Provider.ObjectExists(info)) { return(System.IO.File.ReadAllText(path)); } using (CMS.IO.StreamReader streamReader = CMS.IO.StreamReader.New(Provider .GetObjectContent(info, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read, 4096) )) { return(streamReader.ReadToEnd()); } }
/// <summary> /// Opens a binary file, reads the contents of the file into a byte array, and then closes the file. /// </summary> /// <param name="path">Path to file.</param> public override byte[] ReadAllBytes(string path) { if (!this.Exists(path)) { throw GetFileNotFoundException(path); } IS3ObjectInfo info = S3ObjectFactory.GetInfo(path); if (!File.Provider.ObjectExists(info)) { return(System.IO.File.ReadAllBytes(path)); } System.IO.Stream objectContent = Provider .GetObjectContent(info, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read, 4096); byte[] buffer = new byte[objectContent.Length]; objectContent.Seek(0L, SeekOrigin.Begin); objectContent.Read(buffer, 0, ValidationHelper.GetInteger(objectContent.Length, 0)); objectContent.Close(); return(buffer); }
/// <summary>Initializes file stream object.</summary> protected virtual void InitFileStream() { string path = CMS.IO.Path.Combine(PathHelper.TempPath, PathHelper.GetRelativePath(this.mPath)); Directory.CreateDiskDirectoryStructure(path); this.obj = S3ObjectFactory.GetInfo(this.mPath); if (this.Provider.ObjectExists(this.obj)) { if (this.fileMode == CMS.IO.FileMode.CreateNew) { throw new Exception("Cannot create a new file, the file is already exist."); } this.fsTemp = (System.IO.FileStream) this.Provider.GetObjectContent(this.obj, (System.IO.FileMode) this.fileMode, (System.IO.FileAccess) this.fileAccess, (System.IO.FileShare) this.fileShare, this.bufferSize); if (this.fileMode == CMS.IO.FileMode.Append) { this.fsTemp.Position = this.fsTemp.Length; } } else { if (System.IO.File.Exists(this.mPath)) { this.fsStream = new System.IO.FileStream(this.mPath, (System.IO.FileMode) this.fileMode, (System.IO.FileAccess) this.fileAccess, (System.IO.FileShare) this.fileShare, this.bufferSize); } } if (this.fsTemp != null || this.fsStream != null) { return; } try { this.fsTemp = new System.IO.FileStream(path, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite, (System.IO.FileShare) this.fileShare, this.bufferSize); } catch (FileNotFoundException) { } }
/// <summary> /// Creates all directories and subdirectories as specified by path. /// </summary> /// <param name="path">Path to create.</param> public override CMS.IO.DirectoryInfo CreateDirectory(string path) { path = PathHelper.GetValidPath(path); if (this.Exists(path)) { return(new DirectoryInfo(path)); } IS3ObjectInfo info = S3ObjectFactory.GetInfo(path); info.Key = $"{info.Key}/"; this.Provider.CreateEmptyObject(info); DirectoryInfo directoryInfo = new DirectoryInfo(path) { CreationTime = DateTime.Now, Exists = true, FullName = path }; directoryInfo.LastWriteTime = directoryInfo.CreationTime; directoryInfo.Name = System.IO.Path.GetFileName(path); return(directoryInfo); }
/// <summary>Copies object to another.</summary> /// <param name="sourceObject">Source object info.</param> /// <param name="destObject">Destination object info.</param> public void CopyObjects(IS3ObjectInfo sourceObject, IS3ObjectInfo destObject) { string pathFromObjectKey = PathHelper.GetPathFromObjectKey(destObject.Key, true); CopyObjectRequest request = new CopyObjectRequest() { SourceBucket = sourceObject.BucketName, DestinationBucket = GetBucketName(pathFromObjectKey), SourceKey = sourceObject.Key, DestinationKey = destObject.Key }; if (this.IsPublicAccess(pathFromObjectKey)) { request.CannedACL = S3CannedACL.PublicRead; } CopyObjectResponse copyObjectResponse = this.S3Client.CopyObject(request); destObject.ETag = copyObjectResponse.ETag; destObject.Length = ValidationHelper.GetLong(copyObjectResponse.ContentLength, 0L); FileDebug.LogFileOperation(PathHelper.GetPathFromObjectKey(sourceObject.Key, true) + "|" + PathHelper.GetPathFromObjectKey(destObject.Key, true), nameof(CopyObjects), "Custom Amazon"); RemoveRequestCache(destObject.Key); }
/// <summary>Initializes new instance of FileInfo class.</summary> /// <param name="filename">File name.</param> public FileInfo(string filename) { this.mExtension = CMS.IO.Path.GetExtension(filename); this.mFullName = filename; this.mName = CMS.IO.Path.GetFileName(filename); this.mExists = CMS.IO.File.Exists(filename); this.IsReadOnly = false; this.Attributes = CMS.IO.FileAttributes.Normal; this.obj = S3ObjectFactory.GetInfo(filename); if (!this.Provider.ObjectExists(this.obj)) { if (System.IO.File.Exists(filename)) { this.mSystemInfo = new System.IO.FileInfo(filename); } } else { this.mExists = true; this.existsInS3Storage = true; } this.InitCMSValues(); }
/// <summary> /// Deletes the specified file. An exception is not thrown if the specified file does not exist. /// </summary> /// <param name="path">Path to file</param> public override void Delete(string path) { if (!this.Exists(path)) { throw GetFileNotFoundException(path); } IS3ObjectInfo info1 = S3ObjectFactory.GetInfo(path); if (Provider.ObjectExists(info1)) { Provider.DeleteObject(info1); IS3ObjectInfo info2 = S3ObjectFactory.GetInfo(CMS.IO.Path.GetDirectoryName(path)); info2.Key = $"{info2.Key}/"; if (!Provider.ObjectExists(info2)) { Provider.CreateEmptyObject(info2); } info2.SetMetadata(S3ObjectInfoProvider.LAST_WRITE_TIME, S3ObjectInfoProvider.GetDateTimeString(DateTime.Now)); } else { throw new InvalidOperationException($"File '{path}' cannot be deleted because it exists only in application file system. \r\n This exception typically occurs when file system is mapped to Amazon S3 storage after the file or directory\r\n '{path}' was created in the local file system. To fix this issue remove specified file or directory."); } }
protected void Page_Load(object sender, EventArgs e) { string hash = QueryHelper.GetString("hash", string.Empty); string path = QueryHelper.GetString("path", string.Empty); // Validate hash if (ValidationHelper.ValidateHash("?path=" + URLHelper.EscapeSpecialCharacters(path), hash, false)) { if (path.StartsWithCSafe("~")) { path = Server.MapPath(path); } // Get file content from Amazon S3 IS3ObjectInfo obj = S3ObjectFactory.GetInfo(path); // Check if blob exists if (Provider.ObjectExists(obj)) { // Clear response. CookieHelper.ClearResponseCookies(); Response.Clear(); // Set the revalidation SetRevalidation(); DateTime lastModified = S3ObjectInfoProvider.GetStringDateTime(obj.GetMetadata(S3ObjectInfoProvider.LAST_WRITE_TIME)); string etag = "\"" + lastModified.ToString() + "\""; // Set correct response content type SetResponseContentType(path); // Client caching - only on the live site if (AllowCache && AllowClientCache && ETagsMatch(etag, lastModified)) { // Set the file time stamps to allow client caching SetTimeStamps(lastModified); RespondNotModified(etag, true); return; } Stream stream = Provider.GetObjectContent(obj); SetDisposition(Path.GetFileName(path), Path.GetExtension(path)); // Setup Etag property ETag = etag; if (AllowCache) { // Set the file time stamps to allow client caching SetTimeStamps(lastModified); Response.Cache.SetETag(etag); } else { SetCacheability(); } // Send headers Response.Flush(); Byte[] buffer = new Byte[StorageHelper.BUFFER_SIZE]; int bytesRead = stream.Read(buffer, 0, StorageHelper.BUFFER_SIZE); // Copy data from blob stream to cache while (bytesRead > 0) { // Write the data to the current output stream Response.OutputStream.Write(buffer, 0, bytesRead); // Flush the data to the output Response.Flush(); // Read next part of data bytesRead = stream.Read(buffer, 0, StorageHelper.BUFFER_SIZE); } stream.Close(); CompleteRequest(); } else { NotFound(); } } else { URLHelper.Redirect(ResolveUrl("~/CMSMessages/Error.aspx?title=" + ResHelper.GetString("general.badhashtitle") + "&text=" + ResHelper.GetString("general.badhashtext"))); } }
/// <summary> /// Sets metadata from response acquired from Amazon S3 storage to S3ObjectInfo. /// </summary> /// <param name="obj">Representation of the file on Amazon S3 storage.</param> /// <param name="response">Response acquired from Amazon S3 storage after uploading file.</param> /// <param name="length"> /// Amazon S3 storage does not return length of the uploaded file in <paramref name="response" />, /// if the file was uploaded via multipart upload. In case of multipart upload is <see cref="P:CMS.AmazonStorage.IS3ObjectInfo.Length" /> /// of the <paramref name="obj" /> set via this parameter. /// </param> private void SetS3ObjectMetadaFromResponse(IS3ObjectInfo obj, CompleteMultipartUploadResponse response, long length = 0) { this.SetS3ObjectMetadaFromResponse(obj, response.ETag, response, length); }
/// <summary> /// Sets metadata from response acquired from Amazon S3 storage to S3ObjectInfo. /// </summary> /// <param name="obj">Representation of the file on Amazon S3 storage.</param> /// <param name="response">Response acquired from Amazon S3 storage after uploading file.</param> /// <param name="length"> /// Amazon S3 storage does not return length of the uploaded file in <paramref name="response" />, /// if the file was uploaded via multipart upload. In case of multipart upload is <see cref="P:CMS.AmazonStorage.IS3ObjectInfo.Length" /> /// of the <paramref name="obj" /> set via this parameter. /// </param> private void SetS3ObjectMetadaFromResponse(IS3ObjectInfo obj, PutObjectResponse response, long length = 0) { this.SetS3ObjectMetadaFromResponse(obj, response.ETag, response, length); }
/// <summary>Remove S3 file from temporary local storage.</summary> /// <param name="obj">S3 object to be removed from temporary local storage</param> private static void RemoveFromTemp(IS3ObjectInfo obj) { DeleteFileFromLocalPath(CMS.IO.Path.Combine(PathHelper.TempPath, PathHelper.GetPathFromObjectKey(obj.Key, false))); }
/// <summary>Returns whether object exists.</summary> /// <param name="obj">Object info.</param> public bool ObjectExists(IS3ObjectInfo obj) { return(obj.Exists()); }