2012-11-19 4 views
5

Der Hintergrund dieser Frage basiert auf einem virtuellen Dateisystem, das ich entwickle. Das Konzept, das ich verwende, ist ein virtueller Pfad-Provider für verschiedene Arten von Speichertypen, d. H. Lokales Dateisystem, Dropbox und Amazon S3. Meine Basisklasse für eine virtuelle Datei sieht wie folgt aus:Upload-Datei mit einem virtuellen Pfadanbieter und Amazon S3 SDK

public abstract class CommonVirtualFile : VirtualFile { 
    public virtual string Url { 
     get { throw new NotImplementedException(); } 
    } 
    public virtual string LocalPath { 
     get { throw new NotImplementedException(); } 
    } 
    public override Stream Open() { 
     throw new NotImplementedException(); 
    } 
    public virtual Stream Open(FileMode fileMode) { 
     throw new NotImplementedException(); 
    } 
    protected CommonVirtualFile(string virtualPath) : base(virtualPath) { } 
} 

Die Umsetzung der zweiten Open-Methode ist es, was meine Frage dreht sich alles um. Wenn wir bei meiner Implementierung für das lokale Dateisystem suchen, dh eine Datei auf Festplatte speichern sieht es wie folgt aus:

public override Stream Open(FileMode fileMode) { 
    return new FileStream("The_Path_To_The_File_On_Disk"), fileMode); 
} 

Wenn ich möchte eine Datei auf dem lokalen Dateisystem speichern diese in etwa so aussehen würde:

const string virtualPath = "/assets/newFile.txt"; 
    var file = HostingEnvironment.VirtualPathProvider.GetFile(virtualPath) as CommonVirtualFile; 
    if (file == null) { 
     var virtualDir = VirtualPathUtility.GetDirectory(virtualPath); 
     var directory = HostingEnvironment.VirtualPathProvider.GetDirectory(virtualDir) as CommonVirtualDirectory; 
     file = directory.CreateFile(VirtualPathUtility.GetFileName(virtualPath)); 
    } 
    byte[] fileContent; 
    using (var fileStream = new FileStream(@"c:\temp\fileToCopy.txt", FileMode.Open, FileAccess.Read)) { 
     fileContent = new byte[fileStream.Length]; 
     fileStream.Read(fileContent, 0, fileContent.Length); 
    } 
    // write the content to the local file system 
    using (Stream stream = file.Open(FileMode.Create)) { 
     stream.Write(fileContent, 0, fileContent.Length); 
    } 

Was ich will, ist, dass, wenn ich meinen amazon s3 virtuellen Pfad Anbieter wechsle ich diesen Code wollen so ohne Änderungen direkt zu arbeiten, die Dinge zusammenzufassen, wie kann ich dies die sdk amazon S3 mit lösen und wie Ich implementiere meine Open (FileMode fileMode) -Methode in meinem Amazon s3 Virtual Path Provider?

+0

Sie sollten das [SDK] (http://aws.amazon.com/sdkfornet/) verwenden. –

+0

@AaronMcIver Entschuldigung, meine Frage war zu unscharf .. Ich habe weitere Informationen hinzugefügt – Marcus

+1

Ich denke, was Sie tun müssen, ist ein Interface/Factory-Design, das die verschiedenen SDK-Implementierungen des Cloud Storage Providers berücksichtigt. Stellen Sie sicher, dass Sie keine Patente verletzen, zB [David Ebbos Microsoft-Patente] (http://www.google.com/patents/US20060206452) - was Sie versuchen zu tun, klingt nach einer ziemlich coolen Technologieentwicklung! Viel Glück!! –

Antwort

1

Hey, ich stand auch für dieses Problem, und ich löste es, einen Strom zu implementieren.

Hier ist meine Art, ich habe es vielleicht hilft es:

public static Stream OpenStream(S3TransferUtility transferUtility, string key) 
    {      
     byte[] buffer = new byte[Buffersize + Buffersize/2]; 

     S3CopyMemoryStream s3CopyStream = 
      new S3CopyMemoryStream(key, buffer, transferUtility) 
      .WithS3CopyFileStreamEvent(CreateMultiPartS3Blob); 

     return s3CopyStream; 
    } 

My-Stream mit Konstruktor der Nähe außer Kraft gesetzt und schreiben (array, Offset, count) Methoden und laden den Strom zu Amazon S3 zum Teil.

public class S3CopyMemoryStream : MemoryStream 
    { 

     public S3CopyMemoryStream WithS3CopyFileStreamEvent(StartUploadS3CopyFileStreamEvent doing) 
     { 
      S3CopyMemoryStream s3CopyStream = new S3CopyMemoryStream(this._key, this._buffer, this._transferUtility); 

      s3CopyStream.StartUploadS3FileStreamEvent = new S3CopyMemoryStream.StartUploadS3CopyFileStreamEvent(CreateMultiPartS3Blob); 

      return s3CopyStream; 
     } 

     public S3CopyMemoryStream(string key, byte[] buffer, S3TransferUtility transferUtility) 
      : base(buffer) 
     { 
      if (buffer.LongLength > int.MaxValue) 
       throw new ArgumentException("The length of the buffer may not be longer than int.MaxValue", "buffer"); 

      InitiatingPart = true; 
      EndOfPart = false; 
      WriteCount = 1; 
      PartETagCollection = new List<PartETag>(); 

      _buffer = buffer; 
      _key = key; 
      _transferUtility = transferUtility; 
     } 

Die Veranstaltung StartUploadS3FileStreamEvent ruft einen Anruf, der, uploadpart und vervollständigen den Upload starten.

Alternativ könnten Sie ein Filestream implementieren, die viel einfacher ist, weil Sie

TransferUtilityUploadRequest request = 
      new TransferUtilityUploadRequest() 
      .WithAutoCloseStream(false).WithBucketName(
       transferUtility.BucketName) 
       .WithKey(key) 
       .WithPartSize(stream.PartSize) 
       .WithInputStream(stream) as TransferUtilityUploadRequest; 

     transferUtility.Upload(request); 

am Ende Methode des überschriebenen Filestream verwenden können. Der Nachteil ist, dass Sie zuerst die gesamten Daten auf die Festplatte schreiben müssen und dann können Sie sie hochladen.

+0

Sorry für die späte Antwort, aber ich bin neugierig, wie die Implementierung von Close und Write-Methoden aussehen. Ich habe es geschafft, eine Datei hochzuladen, aber der Inhalt meiner Testdatei ist so beschädigt http://cl.ly/Lbcn – Marcus

+0

Was versuchst du zu tun? Klasse: Memorystream oder Klasse: FileStream? Verwenden Sie die Multipart API oder die TransferUtility-Schnittstelle? Oder versuchst du asynchron zu laden? Verwenden Sie einen Stream oder einen Dateipfad? Vielleicht musst du den Stream erst suchen und dann hochladen? – zirbel

+1

Ich google CreateMultiPartS3Blob und fand einen anderen Beitrag http://Stackoverflow.com/questions/13604916/s3-multi-part-upload-exception von Ihnen und ich bekam die Antwort dort, die Position auf 0 mein Problem behoben. Ich benutze fast die gleiche Implementierung wie in Ihrem Post und es funktioniert gut. Sie haben anscheinend einen festen Puffer in Ihrem Code oder verwenden Sie die Größe der Datei als Pufferlänge? Ich beziehe mich auf diese Codezeile, wenn (Position> = Buffergröße) in Schreibmethode. – Marcus