首页 > 解决方案 > C#如何处理从android上传到C#的多部分文件

问题描述

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

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

请求.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);



    }
}

Response.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();
    }
}

标签: c#restnetworking

解决方案


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

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

Content-Type本质上,您必须从 http 标头boundary=(一旦你得到了边界,你将不得不将请求的主体解析为表单的真正的键/值对。从那里,上传文件的内容将是表单提交的任何键的值。

阅读有关官方 W3 规范的更多信息


推荐阅读