2012-03-12 23 views
0

ファイルをアップロードする方法(500 MBサイズ以上)...穏やかなWebサービスで特定の場所にファイルを保存する方法は?WCF 4.0テンプレート(REST)を使用してファイルをアップロードする方法

リンクがある場合は、共有してください。
サービスをテストするためにFiddlerを使用します。

ここには私が働いているコードがあります。

[WebInvoke(UriTemplate = "Add", Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)] 
public bool UploadFile(FileUploader.File userFile, System.IO.Stream fileStream) 
{ 
    FileUploader.Logic.StreamObject streamUploader = new FileUploader.Logic.StreamObject(); 
    streamUploader.UploadFile(userFile.FileName, fileStream); 
    return true; 
} 



public class StreamObject : IStreamObject 
{ 
    public void UploadFile(string filename, Stream fileStream) 
    { 
     byte[] buffer = new byte[10000]; 
     int bytesRead, totalbytesRead = 0; 
     do 
     { 
      bytesRead = fileStream.Read(buffer, 0, buffer.Length); 
      totalbytesRead += bytesRead; 
     } while (bytesRead > 0); 
    } 
} 

答えて

1

からmultipartParserを手に入れた:以下のようmultipartParserなどと呼ばれるものがあります。次のようにサービスが見えることがあります。

次のようにドキュメントが見えるかもしれ
[ServiceContract] 
public class DocumentService 
{ 
    [OperationContract] 
    [WebTemplate("{name}"] 
    public Document Create(Stream stream, string name) 
    { 
     var id = Guid.NewGuid().ToString("N"); 
     using(FileStream outputStream = File.Create(Path.Combine("c:\\temp\\", id))) 
     { 
      stream.CopyTo(outputStream); 
     } 
     Document document = new Document(); 
     document.Name = name; 
     document.Id = id; 
     // Save document to database 
     // Set headers 
     return document; 
    } 
} 

[DataContract] 
public class Document 
{ 
    [DataMember] 
    public string Id 
    { 
     get;set; 
    } 

    [DataMember] 
    public string Name 
    { 
     get;set; 
    } 

    /* other fields */ 

} 

をサービスにファイルをアップロードするには(それがhttp://api.example.com/documents/であると仮定すると)、次の操作を実行できます。

string name = "mydocument.doc"; 
var request = WebRequest.Create ("http://api.example.com/documents/" + name); 
request.ContentType = "application/octet-stream"; 
request.Method = "POST"; 
using(var stream = request.GetRequestStream()) 
{ 
    using(var inputStream = File.OpenRead("c:\\mydocument.doc")) 
    { 
     inputStream.CopyTo(stream); 
    } 
} 

using(var response = (HttpWebResponse)request.GetResponse()) 
{ 
    // process the response, if needed 
} 

マルチパートストリームを送信する必要がある場合は、ストリームを1つ送信する必要はありません。どんなパラメータ(名前など)もUriTemplateの一部であることが重要です。

+0

File.Open( "c:\\ mydocument.doc")はエラーです。 – fiberOptics

+0

ありがとうございます。 File.OpenReadである必要があります。答えはそれに応じて更新されました。 – bloudraak

+0

こんにちは、私は "ストリームは書き込みをサポートしていません。" on "inputStream.CopyTo(stream);"これは何が問題なのですか? 「//ヘッダーを設定する」とはどういう意味ですか?忍耐をありがとう。 – fiberOptics

1

RESTサービスにファイルをアップロードする方法の例を以下に示します。

private byte[] UseWebClientForFileUpload(string serviceBaseUrl, String resourceUrl, string filePath) 
    { 
     var c = new WebClient(); 
     c.OpenWrite(string.Concat(serviceBaseUrl, resourceUrl), "POST"); 
     c.Headers[HttpRequestHeader.ContentType] = "application/octet-stream";    
     return c.UploadFile(string.Concat(serviceBaseUrl, resourceUrl), filePath); 
    } 

は、適切なコンテンツタイプを設定してください。私は、StreamをParamsの1つとして使用するときに複数のパラメータを渡すことはできないと考えます。ファイル名とストリームを取得するために、すべてを単一のストリームとして渡し、ストリームを分離するパーサーを使用します。

public class MultipartParser 
    { 
     public MultipartParser(Stream stream) 
     { 
      this.Parse(stream, Encoding.UTF8); 
      ParseParameter(stream, Encoding.UTF8); 
     } 

     public MultipartParser(Stream stream, Encoding encoding) 
     { 
      this.Parse(stream, encoding); 
     } 

     private void Parse(Stream stream, Encoding encoding) 
     { 
      this.Success = false; 

      // Read the stream into a byte array 
      byte[] data = ToByteArray(stream); 

      // Copy to a string for header parsing 
      string content = encoding.GetString(data); 

      // The first line should contain the delimiter 
      int delimiterEndIndex = content.IndexOf("\r\n"); 

      if (delimiterEndIndex > -1) 
      { 
       string delimiter = content.Substring(0, content.IndexOf("\r\n")); 

       // Look for Content-Type 
       Regex re = new Regex(@"(?<=Content\-Type:)(.*?)(?=\r\n\r\n)"); 
       Match contentTypeMatch = re.Match(content); 

       // Look for filename 
       re = new Regex(@"(?<=filename\=\"")(.*?)(?=\"")"); 
       Match filenameMatch = re.Match(content); 

       // Did we find the required values? 
       if (contentTypeMatch.Success && filenameMatch.Success) 
       { 
        // Set properties 
        this.ContentType = contentTypeMatch.Value.Trim(); 
        this.Filename = filenameMatch.Value.Trim(); 

        // Get the start & end indexes of the file contents 
        int startIndex = contentTypeMatch.Index + contentTypeMatch.Length + "\r\n\r\n".Length; 

        byte[] delimiterBytes = encoding.GetBytes("\r\n" + delimiter); 
        int endIndex = IndexOf(data, delimiterBytes, startIndex); 

        int contentLength = endIndex - startIndex; 

        // Extract the file contents from the byte array 
        byte[] fileData = new byte[contentLength]; 

        Buffer.BlockCopy(data, startIndex, fileData, 0, contentLength); 

        this.FileContents = fileData; 
        this.Success = true; 
       } 
      } 
     } 

     private void ParseParameter(Stream stream, Encoding encoding) 
     { 
      this.Success = false; 

      // Read the stream into a byte array 
      byte[] data = ToByteArray(stream); 

      // Copy to a string for header parsing 
      string content = encoding.GetString(data); 

      // The first line should contain the delimiter 
      int delimiterEndIndex = content.IndexOf("\r\n"); 

      if (delimiterEndIndex > -1) 
      { 
       string delimiter = content.Substring(0, content.IndexOf("\r\n")); 
       string[] splitContents = content.Split(new[] {delimiter}, StringSplitOptions.RemoveEmptyEntries); 
       foreach (string t in splitContents) 
       { 
        // Look for Content-Type 
        Regex contentTypeRegex = new Regex(@"(?<=Content\-Type:)(.*?)(?=\r\n\r\n)"); 
        Match contentTypeMatch = contentTypeRegex.Match(t); 

        // Look for name of parameter 
        Regex re = new Regex(@"(?<=name\=\"")(.*)"); 
        Match name = re.Match(t); 

        // Look for filename 
        re = new Regex(@"(?<=filename\=\"")(.*?)(?=\"")"); 
        Match filenameMatch = re.Match(t); 

        // Did we find the required values? 
        if (name.Success || filenameMatch.Success) 
        { 
         // Set properties 
         //this.ContentType = name.Value.Trim(); 
         int startIndex; 
         if (filenameMatch.Success) 
         { 
          this.Filename = filenameMatch.Value.Trim(); 
         } 
         if(contentTypeMatch.Success) 
         { 
          // Get the start & end indexes of the file contents 
          startIndex = contentTypeMatch.Index + contentTypeMatch.Length + "\r\n\r\n".Length; 
         } 
         else 
         { 
          startIndex = name.Index + name.Length + "\r\n\r\n".Length; 
         } 

         //byte[] delimiterBytes = encoding.GetBytes("\r\n" + delimiter); 
         //int endIndex = IndexOf(data, delimiterBytes, startIndex); 

         //int contentLength = t.Length - startIndex; 
         string propertyData = t.Substring(startIndex - 1, t.Length - startIndex); 
         // Extract the file contents from the byte array 
         //byte[] paramData = new byte[contentLength]; 

         //Buffer.BlockCopy(data, startIndex, paramData, 0, contentLength); 

         MyContent myContent = new MyContent(); 
         myContent.Data = encoding.GetBytes(propertyData); 
         myContent.StringData = propertyData; 
         myContent.PropertyName = name.Value.Trim(); 

         if (MyContents == null) 
          MyContents = new List<MyContent>(); 

         MyContents.Add(myContent); 
         this.Success = true; 
        } 
       } 
      } 
     } 

     private int IndexOf(byte[] searchWithin, byte[] serachFor, int startIndex) 
     { 
      int index = 0; 
      int startPos = Array.IndexOf(searchWithin, serachFor[0], startIndex); 

      if (startPos != -1) 
      { 
       while ((startPos + index) < searchWithin.Length) 
       { 
        if (searchWithin[startPos + index] == serachFor[index]) 
        { 
         index++; 
         if (index == serachFor.Length) 
         { 
          return startPos; 
         } 
        } 
        else 
        { 
         startPos = Array.IndexOf<byte>(searchWithin, serachFor[0], startPos + index); 
         if (startPos == -1) 
         { 
          return -1; 
         } 
         index = 0; 
        } 
       } 
      } 

      return -1; 
     } 

     private byte[] ToByteArray(Stream stream) 
     { 
      byte[] buffer = new byte[32768]; 
      using (MemoryStream ms = new MemoryStream()) 
      { 
       while (true) 
       { 
        int read = stream.Read(buffer, 0, buffer.Length); 
        if (read <= 0) 
         return ms.ToArray(); 
        ms.Write(buffer, 0, read); 
       } 
      } 
     } 

     public List<MyContent> MyContents { get; set; } 

     public bool Success 
     { 
      get; 
      private set; 
     } 

     public string ContentType 
     { 
      get; 
      private set; 
     } 

     public string Filename 
     { 
      get; 
      private set; 
     } 

     public byte[] FileContents 
     { 
      get; 
      private set; 
     } 
    } 

public class MyContent 
    { 
     public byte[] Data { get; set; } 
     public string PropertyName { get; set; } 
     public string StringData { get; set; } 
    } 

私は答えは私が前にやっていることに由来しhere

+0

こんにちは、あなたはその使用法のいくつかの例を示すことができますか?ありがとう。 – fiberOptics

関連する問題