【问题标题】:creating a webservice that accepts a file (Stream) doesnt want other params创建一个接受文件(流)的 Web 服务不需要其他参数
【发布时间】:2013-11-12 21:08:39
【问题描述】:

我有一个想要上传到 Web 服务的文件,但它需要额外的参数,所以我创建了一些带有关联名称:值对的隐藏字段,以便推送到服务器请求。问题在于服务的定义。

[错误]

合约“IFormServices”中的“NewImage”操作有多个请求主体参数,其中一个是 Stream。 Stream为参数时,body中不能有其他参数。

[接口]

[OperationContract]
    [WebInvoke(Method = "POST",
        ResponseFormat = WebMessageFormat.Json)]
    string NewImage(Stream data, string server,string datasource, string document, string image_id);

[定义]

public string NewImage(Stream data, string server, string datasource, string document, string image_id)
        {
        //this should, similar to others, need a server, datasource, and some sort of document in which to append the images.
        WebClient wsb = new WebClient();
        string str = "_URL_";
        byte[] byte_data = new byte[data.Length];
        data.Read(byte_data, 0, byte_data.Length);
        byte[] response = wsb.UploadData(str,"POST",byte_data);
        string retVal = Convert.ToString(response);
        //want to return a JSON.serialized dictionary of:  given image_id + id returned from response.
        Dictionary<string, object> retDict = new Dictionary<string, object>();
        retDict["filename"] = image_id;
        retDict["id"] = "";
        //return new JavaScriptSerializer().Serialize(json);
        return "-1";
        }

[javascript 代码]

var $form = $("<form />").attr({
                method: "POST",
                enctype: "multipart/form-data",
                target: "image_processing",
                action: "webservices/FormServices.svc/NewImage",
                id: "push_image_to_server"
            } ).appendTo( "body" );
            var im_id = $( this ).attr( "image_id" );
            $( this ).appendTo( "form#push_image_to_server" );
            $( "<input type='hidden' />" ).attr( { name: "server", value: BASE_URL } ).appendTo( $form );
            $( "<input type='hidden' />" ).attr( { name: "datasource", value: SELECTED_DATASOURCE } ).appendTo( $form );
            $( "<input type='hidden' />" ).attr( { name: "document", value: SELECTED_DOCUMENT } ).appendTo( $form );
            $( "<input type='hidden' />" ).attr( { name: "image_id", value: im_id } ).appendTo( $form );
            $("iframe#image_processing").bind("load", function (a,b,c) {
                console.log("SUCCESS", arguments);
                $( "iframe#image_processing" ).unbind( "load", function (a,b,c)
                {
                    console.log( arguments );
                    _IMAGE_UPLOADS_[a["filename"]] = a["id"];
                } );
                $( "form#push_image_to_server" ).remove();
            } );

所以我想找出一种方法将 4 个字符串 + 一个文件发送到服务器。

如何做到这一点?

编辑:将错误代码放在顶部。

【问题讨论】:

    标签: c# javascript asp.net web-services


    【解决方案1】:

    这是 WCF 的一个问题\错误,它在使用 Stream 输入时不接受任何其他参数。

    WCF 也有类似的问题,经过所有研究,我们决定将其他输入参数也转换为流,并使用一些分隔符将其附加到输入

    【讨论】:

    • 有没有办法(IE9稳定版)将一组参数转换为一个流,并将两个流附加在一起?我很想看这个演示。
    【解决方案2】:

    如果NewImage 方法上的string 结果参数是某种唯一标识符,您可以创建第二个方法,称为NewImageAttributes,它接受额外数据以及唯一标识符,然后您可以在您的服务中再次将数据绑定在一起。

    当然,这意味着对服务的两次调用,但它可能会解决您的问题。

    【讨论】:

    • NewImage 确实返回了一个唯一的密钥,但是创建密钥需要参数,并且一旦创建了文件,就根本无法修改。待命,我会快速 ping 服务器团队
    • 好的,等待您的回复,但如果可能的话,将图像上传到一个临时位置(表或文件系统等)并生成一个 Guid。然后使用第一步中的 Guid 上传参数。当服务接收到参数时,它会从临时区域中检索图像,执行原始工作,生成正确的密钥并正常返回。那不行吗?
    • 服务器团队说“那是不行的 Maverick。回到绘图板。” -__- 我想他们最近看了 TopGun
    • 好吧,既然是星期五,TopGun 的参考资料就会得到 +1,尽管他们应该说“这是一个负面的幽灵骑士,模式已满。”
    【解决方案3】:

    只是一个想法 - 使用 HTTP 标头怎么样?然后您可以使用WebOperationContext.IncomingRequest 进行处理。

    【讨论】:

    • 这可能很有趣。如果我决定这样做,我如何制定表单请求以具有这些标头?
    • @Fallenreaper 如果我没记错的话,表单的用途只是将您的变量添加到请求中。看看做POST itself via Ajax + custom headers是否可以替换它。服务器端是similar
    【解决方案4】:

    当您发送流时,它实际上会发送请求中的所有内容。我这样做是为了获取数据:

    public string NewImage(Stream data){
        NameValueCollection PostParameters = HttpUtility.ParseQueryString(new StreamReader(data).ReadToEnd());
        string server = PostParameters["server"],
        string datasource = PostParameters["datasource"], 
        string document = PostParameters["document"];
        string image_id = PostParameters["image_id"];
        var img = PostParameters["File"];
    
        //do other processing...
    }
    

    【讨论】:

      【解决方案5】:

      这篇文章:How to: Create a Service That Accepts Arbitrary Data using the WCF REST Programming Model 描述了另一种发布流和一些数据的方法。

      它们展示了如何随文件一起发送文件名(但您可以添加和/或用任何字符串参数替换它)。

      合同是:

      [ServiceContract]
      public interface IReceiveData
      {
          [WebInvoke(UriTemplate = "UploadFile/{strParam1}/{strParam2}")]
          void UploadFile(string strParam1, string strParam2, Stream fileContents);
      }
      

      公开的服务将通过 POST 接受流以及定义的参数。

      【讨论】:

        【解决方案6】:

        HttpRequest.QueryString[]怎么样?

        [OperationContract]
        [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, UriTemplate = "NewImage")]
        string NewImage(Stream data);
        

        你通过如下 URL 调用它:

        \NewImage?server={server}&datasource={datasource}&document={doc}&image_id={id}
        

        然后在你的代码中:

        public string NewImage(Stream imgStream)
        {
            var request = System.Web.HttpContext.Current.Request;
        
            var server= request.QueryString["server"];
            var datasource = request.QueryString["datasource"];
            var document= request.QueryString["document"];
            var image_id= request.QueryString["image_id"];
        
            ...
        }
        

        我一直在寻找类似的东西,今天偶然发现。

        【讨论】:

          猜你喜欢
          • 2015-09-15
          • 2015-06-14
          • 2014-03-02
          • 1970-01-01
          • 1970-01-01
          • 2013-11-17
          • 2018-04-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多