2012-11-19 16 views
5

Lo sfondo di questa domanda è basato su un file system virtuale che sto sviluppando. Il concetto che sto usando è quello dei provider di percorsi virali per diversi tipi di storage: il file system locale, dropbox e amazon s3. La mia classe di base per un file virtuale è simile al seguente:Carica file utilizzando un provider di percorsi virtuali e 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) { } 
} 

L'attuazione del secondo metodo Open è ciò che la mia domanda è tutto. Se guardiamo alla mia implementazione per il file system locale ovvero il salvataggio di un file su disco che appare così:

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

Se mi piacerebbe salvare un file sul file system locale questo sarebbe simile a questa:

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); 
    } 

quello che voglio è che se posso passare al provider di percorso virtuale il mio Amazon S3 voglio questo codice di lavorare direttamente senza alcuna modifica per così riassumere le cose, come posso risolvere questo utilizzando l'SDK Amazon S3 e come dovrebbe implemento il mio metodo Open (FileMode fileMode) nel mio provider di percorsi virtuali amazon s3?

+0

È necessario utilizzare [SDK] (http://aws.amazon.com/sdkfornet/). –

+0

@AaronMcIver Scusa, la mia domanda è stata confusa .. Ho aggiunto più informazioni – Marcus

+1

Penso che quello che devi fare è creare un'interfaccia/progetto di fabbrica che soddisfi le varie implementazioni di SDK del provider di archiviazione cloud. Verifica che non stai violando nessuno dei loro Brevetti, ad esempio [Brevetti Microsoft di David Ebbo] (http://www.google.com/patents/US20060206452) - quello che stai cercando di fare sembra uno sviluppo tecnologico piuttosto interessante! In bocca al lupo!! –

risposta

1

Hey, anch'io ho riscontrato questo problema e l'ho risolto implementando un flusso.

Qui è il mio modo ho fatto forse aiuta:

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 con il costruttore sostituisce il vicino e scrivere (array, offset, count) metodi e caricare il flusso di Amazon S3 in parte.

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; 
     } 

L'evento StartUploadS3FileStreamEvent invoca una chiamata che avviare, uploadpart e completare il caricamento.

In alternativa si potrebbe implementare un FileStream, che è molto più facile perché è possibile utilizzare

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

     transferUtility.Upload(request); 

al metodo close del FileStream sovresposta. Lo svantaggio è che devi prima scrivere l'intero dato sul disco e poi caricarlo.

+0

Siamo spiacenti per la risposta in ritardo, ma sono curioso di sapere come sarà l'implementazione dei metodi di chiusura e scrittura. Sono riuscito a caricare un file ma il contenuto del mio file di test è corrotto come questo http://cl.ly/Lbcn – Marcus

+0

Che cosa provate a fare? classe: Memorystream o classe: FileStream? Utilizzando l'API Multipart o l'interfaccia TransferUtility? O provi a caricare in modo asincrono? Usi uno stream o un filepath? Forse devi cercare il flusso fino all'inizio e poi caricare? – zirbel

+1

Ho cercato su google CreateMultiPartS3Blob e ho trovato un altro post http://stackoverflow.com/questions/13604916/s3-multi-part-upload-exception da voi e ho ottenuto la risposta, impostando la posizione su 0 risolto il problema. Uso quasi la stessa implementazione del tuo post e funziona perfettamente. Sembra che tu abbia un buffer fisso nel tuo codice o usi la dimensione del file come lunghezza del buffer? Mi riferisco a questa riga di codice se (Posizione> = Bufferizzazione) nel metodo di scrittura. – Marcus

Problemi correlati