2012-04-18 15 views
10

Sto implementando un modulo per caricare file in blocchi da un computer client a un server. Sul lato server sto usando un servizio di sapone WCF.Come posso sbloccare un blocco FileStream?

Per caricare file in blocchi, ho implementato questo esempio da Microsoft http://msdn.microsoft.com/en-us/library/aa717050.aspx. Sono stato in grado di farlo funzionare in uno scenario semplice, quindi carica i file in blocchi. Questo modulo chunking utilizza una WSDualHttpBinding.

Devo implementare una funzionalità per ricaricare un file nel caso in cui il processo di caricamento sia interrotto per qualsiasi motivo (scelta dell'utente, macchina spenta, ecc.) Mentre viene caricato quel file specifico.

Al mio servizio WCF Ho un metodo che gestisce la scrittura di file sul lato server:

pezzi
public void UploadFile(RemoteFileInfo request) 
{ 
FileInfo fi = new FileInfo(Path.Combine(Utils.StorePath(), request.FileName)); 

if (!fi.Directory.Exists) 
{ 
    fi.Directory.Create(); 
} 

FileStream file = new FileStream(fi.FullName, FileMode.Create, FileAccess.Write); 
int count; 
byte[] buffer = new byte[4096]; 
while ((count = request.FileByteStream.Read(buffer, 0, buffer.Length)) > 0) 
{ 
    file.Write(buffer, 0, count); 
    file.Flush(); 
} 
request.FileByteStream.Close(); 
file.Position = 0; 
file.Close(); 

if (request.FileByteStream != null) 
{ 
    request.FileByteStream.Close(); 
    request.FileByteStream.Dispose(); 
} 
} 

Il modulo suddivisione in blocchi sta inviando mentre la funzione request.FileByteStream.Read (buffer, 0, tampone. Lunghezza) viene consumato.

Dopo che il filestream è stato inizializzato, il file viene bloccato (questo è il comportamento normale durante l'inizializzazione di un filestream per la scrittura), ma il problema è che interrompo il processo di caricamento mentre viene eseguito il processo di invio/ricezione , quindi il canale utilizzato dal modulo chunking non viene cancellato, quindi il file rimane bloccato poiché il servizio WCF è ancora in attesa di ulteriori dati da inviare, fino alla scadenza del Timeout di invio (il timeout è di 1 ora poiché devo caricare i file +2.5 GB). Al prossimo caricamento, se provo a caricare lo stesso file, ottengo un'eccezione al servizio WCF perché il filestream non può essere nuovamente inizializzato per lo stesso file.

Vorrei sapere se c'è un modo per evitare/rimuovere il blocco del file, quindi alla prossima esecuzione posso ricaricare lo stesso file anche quando il filestream precedente ha già bloccato il file.

Qualsiasi aiuto sarebbe gradito, grazie.

+0

È ['FileStream.Unlock'] (http://msdn.microsoft.com/en-us/library/system.io.filestream.unlock.aspx) di qualsiasi uso qui? – Xenon

+0

È possibile provare a utilizzare la funzione di costruzione FileStream con il parametro SharingMode impostato su System.IO.FileShare.ReadWrite. –

+0

Ho già provato FileStream.Sblocca ma non risolve il problema poiché il file è stato bloccato da un processo precedente in una precedente chiamata WCF. – Fer

risposta

1

Personalmente non mi piace questo tipo di soluzione. Mantenere la connessione non è l'ideale.

Utilizzando l'esempio, si potrebbe essere a metà strada attraverso un file da 2,5 GB e il processo potrebbe essere interrotto. Finisci nella situazione che hai sopra. Per peggiorare le cose, è necessario inviare nuovamente tutti i dati che sono già stati inviati.

Vorrei seguire personalmente il percorso di gestione dei blocchi e aggiungerli allo stesso lato del file server. Chiama un metodo WCF che indica che un file sta iniziando, carica i dati in blocchi e poi chiama un altro metodo quando il caricamento è completo. Se si è certi che i nomi dei file sono univoci, è possibile ottenere questo risultato con una singola chiamata di metodo.

Qualcosa di simile:

ulong StartFile(string filename) // This returns the data already uploaded 
void UploadFile(string filename, ulong start, byte[] data) 
void EndFile(string filename) // Just as a safety net 

Una semplice soluzione al problema di cui sopra, se non si vuole andare via ho descritto sopra (che non risponde direttamente alla tua domanda) è quello di utilizzare un file temporaneo nome mentre si sta caricando e quindi rinominare il file una volta completato il caricamento. Dovresti davvero adottare questo approccio in ogni caso per evitare che un'applicazione sul server prelevi il file prima che il caricamento sia completato.

Problemi correlati