2012-04-18 8 views
10

Estoy implementando un módulo para cargar archivos en trozos desde una máquina cliente a un servidor. En el lado del servidor estoy usando un servicio WCF Soap.¿Cómo puedo desbloquear un bloqueo FileStream?

Para cargar archivos en trozos, he implementado este ejemplo de Microsoft http://msdn.microsoft.com/en-us/library/aa717050.aspx. Pude hacerlo funcionar en un escenario simple, por lo que sube los archivos en fragmentos. Este módulo de fragmentación está utilizando WSDualHttpBinding.

Necesito implementar una característica para volver a cargar un archivo en caso de que el proceso de carga se detenga por cualquier motivo (elección del usuario, máquina apagada, etc.) mientras se carga ese archivo específico.

En mi servicio WCF Tengo un método que controla la escritura de archivos en el lado del servidor:

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

El módulo de fragmentación está enviando mientras que la función request.FileByteStream.Read (buffer, 0, tampón. Longitud) está siendo consumido.

Después de inicializar filestream, el archivo se bloquea (este es el comportamiento normal al inicializar una ruta de archivos para escritura), pero el problema es que detengo el proceso de carga mientras se realiza el proceso de envío/recepción , entonces el canal utilizado por el módulo de fragmentación no se cancela, por lo que el archivo permanece bloqueado porque el servicio WCF aún espera que se envíen más datos, hasta que expira el tiempo de espera de envío (el tiempo de espera es de 1 hora ya que necesito subir archivos +2.5 GB). En la siguiente carga, si intento cargar el mismo archivo, recibo una excepción en el servicio WCF porque el filestream no se puede inicializar nuevamente para el mismo archivo.

Me gustaría saber si hay una manera de evitar/eliminar el bloqueo de archivos, por lo que en la siguiente ejecución puedo volver a cargar el mismo archivo incluso cuando la anterior filestream ya bloqueó el archivo.

Cualquier ayuda sería apreciada, gracias.

+0

¿Está ['FileStream.Unlock'] (http://msdn.microsoft.com/en-us/library/system.io.filestream.unlock.aspx) de algún uso aquí? – Xenon

+0

Puede probar el uso del constructor FileStream con el parámetro SharingMode establecido en System.IO.FileShare.ReadWrite. –

+0

Ya probé FileStream.Desbloquee pero no resuelve el problema ya que el archivo fue bloqueado por un proceso previo en una llamada WCF anterior. – Fer

Respuesta

1

No me gusta personalmente este tipo de solución. Mantener la conexión no es ideal.

Usando su ejemplo, podría estar a la mitad de un archivo de 2.5GB y el proceso podría abortarse. Terminas en la situación que tienes arriba. Para empeorar las cosas, debe volver a enviar todos los datos que ya se han enviado.

Iría por la ruta de manejar los bloques yo mismo y anexarlos al mismo servidor de archivos. Llame a un método WCF que indica que un archivo se está iniciando, cargue los datos en bloques y luego llame a otro método cuando se complete la carga. SI confía en que los nombres de los archivos son únicos, puede incluso lograrlo con una sola llamada a un método.

Algo así como:

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 solución sencilla para el problema anterior, si usted no quiere ir a la ruta que he descrito (que no responde a su pregunta directamente) es utilizar un archivo temporal nombre mientras está cargando y luego cambie el nombre del archivo una vez que se complete la carga. En realidad, debería adoptar este enfoque para evitar que una aplicación en el servidor recoja el archivo antes de que se complete la carga.

Cuestiones relacionadas