using System; using System.Collections.Generic; using System.Data; using System.Data.Objects; using System.Data.Services; using System.Data.Services.Providers; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Web; using System.Web.Hosting; using DevExpress.XtraPrinting.Native; using iBemsDataService.Model; using iBemsDataService.Util; namespace iBemsDataService { public interface IImageSource { byte[] Image { get; } } /* * 두번째 에 * m:HasStream="true" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" * 를 수동으로 추가하여야 한다. * * */ public class ImageStreamProvider : IDataServiceStreamProvider, IDisposable { private string _tempFile; private string _filePath; private CmFile _cachedEntity; private iBemsEntities _context; private static Dictionary _fileCategories = new Dictionary(); public ImageStreamProvider( iBemsEntities context ) { _context = context; // Get the physical path to the app_data directory used to store the image files. _filePath = HostingEnvironment.MapPath( "~/App_Data/" ); // Create a temp file to store the new images during POST operations. _tempFile = Path.GetTempFileName(); } public void DeleteStream( object entity , DataServiceOperationContext operationContext ) { var file = entity as CmFile; if( file == null ) { throw new DataServiceException( 500 , "Internal Server Error." ); } try { // Delete the requested file by using the key value. File.Delete( FileCategoryManager.GetInstance().GetFilePath( file ) ); } catch( IOException ex ) { throw new DataServiceException( "The file could not be found." , ex ); } } public Stream GetReadStream( object entity , string etag , bool? checkETagForEquality , DataServiceOperationContext operationContext ) { if( checkETagForEquality != null ) { throw new DataServiceException( 400 , "This service does not support the ETag header for a media resource." ); } var file = entity as CmFile; if( file == null ) { throw new DataServiceException( 500 , "Internal Server Error." ); } // Build the full path to the stored image file, which includes the entity key. string filePath = FileCategoryManager.GetInstance().GetFilePath( file ); if( !File.Exists( filePath ) ) { throw new DataServiceException( 500 , "The file could not be found." ); } if ( IsImageType( file ) == false ) { //operationContext.ResponseHeaders["Content-Disposition"] = "attachment; filename=\"" + file.Name + "\""; //operationContext.ResponseHeaders["Content-Disposition"] = "attachment; filename=" + "//" + file.Name + "//"; //operationContext.ResponseHeaders["Content-Disposition"] = "attachment; filename=" + file.Name; /* string contentDisposition; if (Request.Browser.Browser == "IE" && (Request.Browser.Version == "7.0" || Request.Browser.Version == "8.0")) contentDisposition = "attachment; filename=" + Uri.EscapeDataString(fileName); else if (Request.UserAgent != null && Request.UserAgent.ToLowerInvariant().Contains("android")) // android built-in download manager (all browsers on android) contentDisposition = "attachment; filename=\"" + MakeAndroidSafeFileName(fileName) + "\""; else contentDisposition = "attachment; filename=\"" + fileName + "\"; filename*=UTF-8''" + Uri.EscapeDataString(fileName); Response.AddHeader("Content-Disposition", contentDisposition); */ string strDispos = "attachment; filename= " + Uri.EscapeDataString(file.Name); //string strDispos = "attachment; filename=\"" + file.Name + "\"; filename*=UTF-8''" + Uri.EscapeDataString(file.Name); operationContext.ResponseHeaders["Content-Disposition"] = strDispos; } // Return a stream that contains the requested file. return new FileStream( filePath, FileMode.Open ); } protected bool IsImageType( CmFile file ) { var types = file.ContentType.Split( '/' ); return ( types.Length > 0 && types[0].ToLower() == "image" ); } public Uri GetReadStreamUri( object entity , DataServiceOperationContext operationContext ) { return null; } public string GetStreamContentType( object entity , DataServiceOperationContext operationContext ) { var file = entity as CmFile; if( file == null ) { throw new DataServiceException( 500 , "Internal Server Error." ); } return file.ContentType; } public string GetStreamETag( object entity , DataServiceOperationContext operationContext ) { return null; } public Stream GetWriteStream( object entity , string etag , bool? checkETagForEquality , DataServiceOperationContext operationContext ) { if( checkETagForEquality != null ) { throw new DataServiceException( 400 , "This service does not support ETags associated with BLOBs" ); } var file = entity as CmFile; if( file == null ) { throw new DataServiceException( 500 , "Internal Server Error: " + "the Media Link Entry could not be determined." ); } // Handle the POST request. if( operationContext.RequestMethod == "POST" ) { // Set the file name from the Slug header; if we don't have a // Slug header, just set a temporary name which is overwritten // by the subsequent MERGE request from the client. file.Name = operationContext.RequestHeaders["Slug"] ?? "newFile"; // Set the required DateTime values. file.CreatedDate = DateTime.Today; // Set the content type, which cannot be null. file.ContentType = operationContext.RequestHeaders["Content-Type"]; // Cache the current entity to enable us to both create a key based storage file name // and to maintain transactional integrity in the disposer; we do this only for a POST request. _cachedEntity = file; return new FileStream( _tempFile , FileMode.Open ); } // Handle the PUT request else { // Return a stream to write to an existing file. return new FileStream( FileCategoryManager.GetInstance().GetFilePath( file ) , FileMode.Open , FileAccess.Write ); } } public string GetFileCategoryPath( string fileCategoryName ) { var sb = new StringBuilder(); sb.Append( _filePath ); sb.Append( "files/" ); sb.Append( fileCategoryName ); return sb.ToString(); } public string ResolveType( string entitySetName , DataServiceOperationContext operationContext ) { if ( entitySetName == "CmFile" ) { return "BemsDataService." + entitySetName; } return null; } public int StreamBufferSize { get { return 64000; } } public void Dispose() { // If we have a cached entity, it must be a POST request. if( _cachedEntity != null ) { // Get the new entity from the Entity Framework object state manager. var state = _context.Entry( _cachedEntity ).State; if( state == EntityState.Unchanged ) { // Since the entity was created successfully, move the temp file into the // storage directory and rename the file based on the new entity key. File.Move( _tempFile , FileCategoryManager.GetInstance().GetFilePath( _cachedEntity ) ); // Delete the temp file. File.Delete( _tempFile ); } else { // A problem must have occurred when saving the entity to the database, // so we should delete the entity and temp file. _context.CmFile.Remove( _cachedEntity ); _context.SaveChanges(); File.Delete( _tempFile ); throw new DataServiceException( "An error occurred. The file could not be saved." ); } } } } }