【问题标题】:C# how to handle multipart file uploaded from android to C#C#如何处理从android上传到C#的多部分文件
【发布时间】:2018-12-03 12:06:47
【问题描述】:

我正在将 excel 文件从 android 上传到 C#,来自 android 的请求正在到达 c# 服务器(我不想使用 asp.net)。

我从头构建了一个简单的 HTTPServe,我不知道如何在 c# 中处理多部分数据上传,这是我的代码:

Request.cs:

  class Request
{

    public String type { get; set; }
    public String url { get; set; }

    public String host { get; set; }

    private Request(String type,String url,String host)
    {
        this.type = type;

        this.url = url;

        this.host = host;
    }


    public static Request GetRequest(String request)
    {
        if (String.IsNullOrEmpty(request))
            return null;

        String[] tokens = request.Split(' ');      

        String type = tokens[0];

        String url = tokens[1];

        String host = tokens[4];




        return new Request(type, url, host);



    }
}

响应.cs: 类响应 {

    private Byte[] data = null;

    private String status;

    private String mime;


    private Response(String status,String mime,Byte[] data)
    {
        this.status = status;
        this.data = data;
        this.mime = mime;

    }


    public static Response From(Request request)
    {

        Console.WriteLine(request.type);
        if (request == null)
            return MakeNullRequest();



        if (request.type.Equals("POST"))
        {
            return UploadCompleteResponse(request);

        }

        return MakeFromExcel();

    }




    private static Response UploadCompleteResponse(Request request)
    {   //Handling the multipart request here but I don't know how that is a simple example 
        Console.WriteLine("uploaded!!");
        byte[] bytes = Encoding.ASCII.GetBytes("uploaded!!");

        return new Response("ok 200","text/plain",bytes);


    }



    //private static Response MakeFromFile(FileInfo f)
    //{
    //  // to do later 
    //    //return new Response("200 ok", "text/html", d);
    //}



    //Retruning an excel file response  
    private static Response MakeFromExcel()
    {
        String file = Environment.CurrentDirectory + HTTPServer.EXCEL_DIR+"brains.xlsx";
        Console.WriteLine(file);
        FileInfo info = new FileInfo(file);
        if (info.Exists)
        {
            FileStream fs = info.OpenRead();
            BinaryReader read = new BinaryReader(fs);
            Byte[] d = new Byte[fs.Length];
            read.Read(d, 0, d.Length);
            fs.Close();
            return new Response("200 ok", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", d);
        }

        return PageNotFound();


    }

    private static Response MakeNullRequest()
    {

        String file = Environment.CurrentDirectory+HTTPServer.MSG_DIR +"400.html";
        Console.WriteLine(file);
        FileInfo info = new FileInfo(file);
        FileStream fs=info.OpenRead();
        BinaryReader read=new BinaryReader(fs);
        Byte[] d = new Byte[fs.Length];
        read.Read(d, 0, d.Length);

        fs.Close();
        return new Response("400 Bad Request", "text/html", d);
    }


    private static Response PageNotFound()
    {

        String file = Environment.CurrentDirectory + HTTPServer.MSG_DIR + "400.html";
        FileInfo info = new FileInfo(file);
        FileStream fs = info.OpenRead();
        BinaryReader read = new BinaryReader(fs);
        Byte[] d = new Byte[fs.Length];
        read.Read(d, 0, d.Length);
        return new Response("404 Not Found", "text/html", d);
    }

    public void Post(NetworkStream stream)
    {
        StreamWriter writer = new StreamWriter(stream);

        writer.WriteLine(String.Format("{0} {1}\r\nServer: {2}\r\nContent-Type: {3}\r\nAccept-Ranges: 255 bytes\r\nContent-Length: {4}\r\n", HTTPServer.VERSION
            , status, HTTPServer.NAME, mime, data.Length));
        writer.Flush();
        stream.Write(data, 0, data.Length);
        stream.Flush();
        stream.Close();

    }
}

在上面的代码中,我使用了不止一种类型的响应,您可以通过增加令牌数组的大小来访问请求字段。

HTTServer.cs:

    class HTTPServer
{
    public const String MSG_DIR = "\\root\\msg\\";
    public const String EXCEL_DIR = "\\root\\excel\\";
    public const String WEB_DIR = "\\root\\web\\";
    public const String VERSION = "HTTP/1.1";
    public const String NAME = "Thecode007 HTTP SERVER v 1.0";
    private bool running = false;

    private TcpListener listener;



    public HTTPServer(int port)
    {
        listener = new TcpListener(IPAddress.Any,port);
    }


    public void Start() {

        Thread serverThread = new Thread(new ThreadStart(Run));

        serverThread.Start();

    }


    private void Run()
    {

        running = true;

        listener.Start();

        while (running)
        {

            Console.WriteLine("Waiting for connection...");
            TcpClient client = listener.AcceptTcpClient();

            HandleClient(client);

              Console.WriteLine("Client connected!");





        }

        running = false;

         listener.Stop();
    }

    private void HandleClient(TcpClient client)
    {
        StreamReader reader = new StreamReader(client.GetStream());

        String msg = "";

        while (reader.Peek() != -1)
        {

            msg += reader.ReadLine()+"\n";

        }



        Console.WriteLine(msg);


        Request req = Request.GetRequest(msg);

        Response resp = Response.From(req);


        resp.Post(client.GetStream());
    }



}

这里是主要方法:

class Program
{
    static void Main(string[] args)
    {


        Console.WriteLine("Starting Serving on port 9000");

        HTTPServer server = new HTTPServer(9000);

        server.Start();

        Console.ReadLine();
    }
}

【问题讨论】:

  • 下载并安装 .net 的 Ace 提供程序。它有一个 Excel 扩展。周围有很多通过 ADO.net 读取 Excel 文件的示例。一旦你有了一个数据表,你就准备好了。
  • 我不需要 ace 提供程序,我只需要知道如何处理任何文件的多部分数据并将其保存在磁盘上它是核心网络的事情..我想知道如何处理它而不是使用一些框架......我想保存那个excel而不是阅读它所以ado .net什么都不做。
  • 抱歉打扰了。我不想告诉你,但你正在使用“一些框架”。
  • 你没有明白我的意思...Ado 不是处理后获取多部分上传下载请求的 networkibg 核心功能它是数据库 stuf...我需要使用 plaun c# 而不使用框架,即 3rd党图书馆..
  • C# 建立在 .Net 框架之上。我没有提到第 3 方库。再次抱歉,打扰您了。

标签: c# rest networking


【解决方案1】:

免责声明:你不应该直接使用 TcpClient 编写 HTTP 服务器来进行任何生产工作。需要说明的规范太多了,而 C# 已将这些规范内置到您使用的任何 Asp.Net Web 服务器中。

话虽如此,对于一个练习来说,这是一个以特定方式解析请求的问题。你应该可以参考这些问题来了解更多关于多部分边界的细节:

本质上,您必须从 http 标头 (Content-Type) 中读取标头,并解析 boundary= 的值以确定在请求正文中分隔多部分表单的键/值对的原因。一旦你有了边界,你将不得不将请求的主体解析为表单的真正的键/值对。从那里,上传文件的内容将是表单提交的任何键的值。

Read more on the official W3 spec

【讨论】:

  • 我知道它的样子,但我不知道如何处理它???,如何获取帖子数据???...我已经在 java 中处理它,但在 C#我不知道,因为我是新手..
  • @Neil 谢谢我在客户端上的响应与服务器的文本/纯文本响应不兼容,因此会话在第一个分区后关闭,这就是它关闭连接的原因...
  • 很高兴你知道了!
【解决方案2】:

响应.cs:

 class Response
   {

    private Byte[] data = null;

    private String status;

    private String mime;


    private Response(String status,String mime,Byte[] data)
    {
        this.status = status;
        this.data = data;
        this.mime = mime;

    }


    public static Response From(Request request)
    {


        if (request == null)
            return MakeNullRequest();



        if (request.type.Equals("POST"))
        {
            return UploadCompleteResponse(request);

        }

        return MakeFromExcel();

    }




    private static Response UploadCompleteResponse(Request request)
    {  //I added on the rquest array the datapart which contains data
       String data=request.data;


        byte[] bytes = Encoding.ASCII.GetBytes("uploaded!!");

        return new Response("ok 200","text/plain",bytes);


    }



    //private static Response MakeFromFile(FileInfo f)
    //{
    //  // to do later 
    //    //return new Response("200 ok", "text/html", d);
    //}



    //Retruning an excel file response  
    private static Response MakeFromExcel()
    {
        String file = Environment.CurrentDirectory + HTTPServer.EXCEL_DIR+"brains.xlsx";
        Console.WriteLine(file);
        FileInfo info = new FileInfo(file);
        if (info.Exists)
        {
            FileStream fs = info.OpenRead();
            BinaryReader read = new BinaryReader(fs);
            Byte[] d = new Byte[fs.Length];
            read.Read(d, 0, d.Length);
            fs.Close();
            return new Response("200 ok", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", d);
        }

        return PageNotFound();


    }

    private static Response MakeNullRequest()
    {

        String file = Environment.CurrentDirectory+HTTPServer.MSG_DIR +"400.html";
        Console.WriteLine(file);
        FileInfo info = new FileInfo(file);
        FileStream fs=info.OpenRead();
        BinaryReader read=new BinaryReader(fs);
        Byte[] d = new Byte[fs.Length];
        read.Read(d, 0, d.Length);

        fs.Close();
        return new Response("400 Bad Request", "text/html", d);
    }


    private static Response PageNotFound()
    {

        String file = Environment.CurrentDirectory + HTTPServer.MSG_DIR + "400.html";
        FileInfo info = new FileInfo(file);
        FileStream fs = info.OpenRead();
        BinaryReader read = new BinaryReader(fs);
        Byte[] d = new Byte[fs.Length];
        read.Read(d, 0, d.Length);
        return new Response("404 Not Found", "text/html", d);
    }

    public void Post(NetworkStream stream)
    {

        try
        {
               StreamWriter writer = new StreamWriter(stream);

        writer.WriteLine(String.Format("{0} {1}\r\nServer: {2}\r\nContent-Type: {3}\r\nAccept-Ranges: 255 bytes\r\nContent-Length: {4}\r\n", HTTPServer.VERSION
            , status, HTTPServer.NAME, mime, data.Length));
        writer.Flush();
        stream.Write(data, 0, data.Length);
        stream.Flush();

        stream.Close();

        }catch(Exception  ex){


        }




    }
}

Request.cs:

    class Request
{

    public String type { get; set; }
    public String url { get; set; }

    public String host { get; set; }


    public String data { get; set; }




    private Request(String type,String url,String host)
    {
        this.type = type;

        this.url = url;

        this.host = host;
    }

    private Request(String type, String url, String host,String data)
    {
        this.type = type;

        this.url = url;

        this.host = host;

        this.data = data;
    }


    public static Request GetRequest(String request)
    {
        if (String.IsNullOrEmpty(request))
            return null;

        String[] tokens = request.Split(' ');      

        String type = tokens[0];

        String url = tokens[1];

        String host = tokens[4];
        String data = "N/A";
        if (tokens.Length >= 9)
        {
            data = tokens[8];



        }

        return new Request(type, url, host, data);



    }
}

其次,我的 android 客户端期望响应是 responsbody 类型而不是纯文本,这就是为什么从未发送数据的原因......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-22
    • 2011-03-28
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多