2016-06-02 2 views
0

У меня есть службы WCF, которая работает в нестандартном формате, используя потоки:Удалить временный файл после возвращения в сыром виде в WCF

[ServiceContract] 
public interface IEncryptingService 
{ 
    [WebInvoke(UriTemplate = "/")] 
    [OperationContract] 
    Stream SignDocument(Stream requestStream); 
} 

public class EncryptingService : IEncryptingService 
{ 
    public Stream SignDocument(Stream requestStream) 
    { 
     string originalFileName = Path.GetTempFileName(); 
     string signedFileName = Path.GetTempFileName(); 

     using (var originalFileStream = File.Open(originalFileName, FileMode.Create, FileAccess.Write)) 
     { 
      requestStream.CopyTo(originalFileStream); 
     } 

     XmlDocumentSigner.SignFile(originalFileName, signedFileName); 

     return File.Open(signedFileName, FileMode.Open, FileAccess.Read); 
    } 
} 

Теперь, как я могу удалить этот файл после того, как WCF заканчивается возвратом файла?

Я попытался использовать блок finally, но он вызывается сразу после return и выдает исключение, так как файл все еще используется процессом.

Конечно, это обходной путь, как работник фона, ожидающий наличия файла для удаления, но, на мой взгляд, это не похоже на то, как веб-сервисы должны быть реализованы.

+2

Не удается избежать использования файлов в первую очередь? Вместо этого использовать (в памяти) потоки? –

+0

@ Christian.K К сожалению, 'XmlDocumentSigner' является оберткой вокруг внешней неуправляемой библиотеки DLL, которая использует очень специфические алгоритмы (без управляемых или не файловых альтернативных библиотек) и может только подписывать файлы :( –

ответ

1

Решение приходит на ум непростительно быстро, и это абсолютно логично: я могу просто прочитать содержимое файла в памяти и удалить файл.

public Stream SignDocument(Stream requestStream) 
{ 
    string originalFileName = Path.GetTempFileName(); 
    string signedFileName = Path.GetTempFileName(); 

    using (var originalFileStream = File.Open(originalFileName, FileMode.Create, FileAccess.Write)) 
    { 
     requestStream.CopyTo(originalFileStream); 
    } 

    XmlDocumentSigner.SignFile(originalFileName, signedFileName); 

    byte[] signedFileBytes = File.ReadAllBytes(signedFileName); 
    File.Delete(signedFileName); 
    return new MemoryStream(signedFileBytes); 
} 

Обратите внимание, что using заявление делает этот код не в состоянии, а также:

using (var ms = new MemoryStream(signedFileBytes)) 
{ 
    return ms; 
} 
+1

Вы избили меня до него сделанный в поиске вашего ответа. Ваша тоже была менее сложная версия! – TheLethalCoder

+0

@TheLethalCoder Спасибо :) –

+0

Смотрите также: https://devdump.wordpress.com/2008/12/07/disposing-return-values/. Они говорят об утилизации, но вы можете подписаться на OperationCompleted и удалить свой файл там. Это лучше, чем копирование всего файла в память. – Evk

1

Я не пробовал, но вы можете открыть файл и записать этот поток в другой поток. Что-то вроде:

MemoryStream ms = new MemoryStream(); 
using (FileStream fs = File.OpenRead(signedFileName)) 
{ 
    //Read from fs and write to ms 
} 

Тогда все, что вам нужно сделать, это позвонить удалить файл и вернуть ms:

File.Delete(signedFileName); 
return ms;