none
(C++/CX) 使用HTTP/1.1 POST上傳檔案至 C# Web Service RRS feed

  • 问题

  • C# Web Service Function is declared as:

    public UploadFile(byte[] file, string FileName)

    The test form says the request should take this form:

    POST address_of_service HTTP/1.1Host: <host>Content-Type: application/x-www-form-urlencodedContent-Length: length
    
    file= string& file= string& FileName= string

    How do I get my binary file data into that form? I've tried just converting the file data to a string and putting it in the body ( file=<string_data> ) but I get HTTP 500 errors back, complaining about cannot  convert < string_data> to System.Byte. I've got HTTP POST working fine elsewhere in my application with plain string parameters.

    Also, out of curiosity, why is it showing the file parameter twice?

    2014年4月15日 10:28

答案

  • Hi waterrock,

    对于测试页面上的两个file必须是string的说法还是看不懂,以前没有遇到过这么写的API说明文档,既然是file怎么会固定成string格式,不过你可以尝试直接把file=byte[]这个直接上传看看可行否。

    关于在C++/CX中使用web service这个问题,有几个解决办法:

    1,使用C++ REST SDK协助: C++ REST SDK (Codename "Casablanca")

    2,参考一下这个文档:Connecting to networks and web services

    希望能帮到你吧。

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    2014年4月18日 5:53
    版主
  • 或者还有一个办法,你建立一个C#的项目,包含Web Service通信,然后再C++项目中引用。

    具体可以参考:Creating Windows Runtime Components in C# and Visual Basic

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    2014年4月18日 6:13
    版主

全部回复

  • Hi waterrock,

    目前我不知道你C#代码中是具体怎么上传的,不过看样子你可以添加HttpClient的Header属性。你能提供更多的信息么?

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    2014年4月16日 9:58
    版主
  • Hi James,

    server端的部分是由另外的單位用c#開發,因此我只有url位址。

    client端我是用c++/cx,c++不像c#有Add Service Reference可以使用。

    所以我選擇用http post的方式,參考官網的範例HttpClient Sample

    http://code.msdn.microsoft.com/windowsapps/HttpClient-sample-55700664

    測試頁上的說明是這樣

    POST address_of_service HTTP/1.1

    Host: <host>

    Content-Type: application/x-www-form-urlencoded

    Content-Length: length

    file= string& file= string& FileName= string

    所以我把HttpClient Sample的Content-Type改為application/x-www-form-urlencoded

    task<wstring> HttpRequest::PostAsync(Uri^ uri, const wstring& body, cancellation_token cancellationToken)
    {
        int length = 0;
        ComPtr<IStream> postStream;
        CreateMemoryStream(&postStream);

        if (body.length() > 0)
        {
            // Get the required buffer size.
            int size = WideCharToMultiByte(CP_UTF8,                         // UTF-8
                                           0,                               // Conversion type
                                           body.c_str(),                    // Unicode string to convert
                                           static_cast<int>(body.length()), // Size
                                           nullptr,                         // Output buffer
                                           0,                               // Output buffer size
                                           nullptr,
                                           nullptr);
            CheckHResult((size != 0) ? S_OK : HRESULT_FROM_WIN32(GetLastError()));

            std::unique_ptr<char[]> tempData(new char[size]);
            length = WideCharToMultiByte(CP_UTF8,                         // UTF-8
                                         0,                               // Conversion type
                                         body.c_str(),                    // Unicode string to convert
                                         static_cast<int>(body.length()), // Size
                                         tempData.get(),                  // Output buffer
                                         size,                            // Output buffer size
                                         nullptr,
                                         nullptr);
            CheckHResult((length != 0) ? S_OK : HRESULT_FROM_WIN32(GetLastError()));
            CheckHResult(postStream->Write(tempData.get(), length, nullptr));
        }

        return DownloadAsync(L"POST",
                             uri->AbsoluteUri->Data(),
                             cancellationToken,
                             L"application/x-www-form-urlencoded",
                             postStream.Get(),
                             length);
    }

    在c++/cx中,不知道如何把byte轉成string的型式以post傳遞出去?

    Thanks

    2014年4月17日 3:28
  • Hi waterrock,

    关于怎么把byte[]转化成string应该不是难事,下面的是C#代码,不过改写成C++应该也不难,参考DataReader class

    DataReader dataReader = Windows.Storage.Streams.DataReader.FromBuffer(buffer);
    string text = dataReader.ReadString(buffer.Length);

    不过同样还有一个问题在于你为什么会有两个file = xxx存在,毕竟你服务器只接受一个file,那第二个file所带的内容岂不是丢失了?

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    2014年4月17日 8:40
    版主
  • 使用DataReader 把byte[] 轉成string 出現的錯誤訊息:

    ============================================================================

    First-chance exception at 0x767C4B32 in DentalPageApp.exe: Microsoft C++ exception: Platform::COMException ^ at memory location 0x0370C2E4. HRESULT:0x80070459 在多位元組的目的字碼頁中,沒有這個 Unicode 字元可以對應到的字元。

    WinRT information: 在多位元組的目的字碼頁中,沒有這個 Unicode 字元可以對應到的字元。

    ============================================================================

    關於post時為什麼會出現兩個file=string 的變數存在,我也不是很清楚,我是看測試頁上的使用說明。

    因為在c#中以Add Service Reference加進來的UploadFile Function 是只有一個byte[] file 變數。

    還是有什麼其他方式,可以在跨平台的情況上傳檔案??

    Thanks

    2014年4月17日 9:12
  • 可以预料到这个错误,因为你的byte[]可能并不是从string转化而来,如果说这个byte[]从image转化来的话,那根本没法转化成string,强制转化就会有这个错误产生。我建议你去联系一下编写server的人员,问一下string到底是怎么回事。

    不过你第一个帖子的一句话说server端接收数据的API为这个,那么是可以接受byte[]的啊,为什么还要转化为string呢。

    public UploadFile(byte[] file, string FileName)

    至于其他方式来跨平台传文件,要么就是WCF,要么就是socket,没有其他方式了。

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    2014年4月17日 9:32
    版主
  • Hi James,

    因為我client是用c++/cx開發,沒有Add Service Reference的選項。

    沒辦法直接使用UploadFile的fucntion。

    public UploadFile(byte[] file, string FileName) 的宣告說明,是我開啟c#應用程式,然後透過Add Service Reference的方式看到的。

    因為HttpClient Sample中的post body部分是string,所以才想說把byte轉成string去上傳。

    Thanks

    2014年4月17日 11:43
  • Hi waterrock,

    对于测试页面上的两个file必须是string的说法还是看不懂,以前没有遇到过这么写的API说明文档,既然是file怎么会固定成string格式,不过你可以尝试直接把file=byte[]这个直接上传看看可行否。

    关于在C++/CX中使用web service这个问题,有几个解决办法:

    1,使用C++ REST SDK协助: C++ REST SDK (Codename "Casablanca")

    2,参考一下这个文档:Connecting to networks and web services

    希望能帮到你吧。

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    2014年4月18日 5:53
    版主
  • 或者还有一个办法,你建立一个C#的项目,包含Web Service通信,然后再C++项目中引用。

    具体可以参考:Creating Windows Runtime Components in C# and Visual Basic

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    2014年4月18日 6:13
    版主