【问题标题】:Send image with HttpClient to POST WebApi and consume the data使用 HttpClient 发送图像到 POST WebApi 并使用数据
【发布时间】:2019-10-28 08:38:52
【问题描述】:

我的HttpClient 使用PostAsync 发送图像。 我不确定现在该做什么,因为这是我的第一个 REST Api,我还不能真正调整我在其他帖子中整理的内容。 希望大家能帮帮我,给我一个方向。

public async Task SendImage(string fullFileName, string fileName)
    {            
        var client = new HttpClient();
        client.BaseAddress = new Uri("http://x.x.x.x");

        var content = new StringContent(fullFileName, Encoding.UTF8, "image/jpg");
        HttpResponseMessage response = await client.PostAsync($"/values/file/{fileName}", content);
    }

我有几个关于 POST 功能的问题。 首先我可以用PostMan成功访问它,fileName是正确的。

如何读取图像数据并将其写入文件?

[HttpPost("file/{fileName}")]
public void Upload(string fileName)
{        
    Debug.Write(fileName);
}

编辑:

我设置了我的环境,现在我可以通过 Internet 将帖子发送到我发布的 Web Api。 在我的应用程序上什么也没有发生。 现在我只是想得到一些信息来处理,但我没有得到。

[HttpPost("file/{fileName}")]
public HttpResponseMessage Upload(UploadedFile fileName)
{
    Debug.Write(fileName);
    if (!ModelState.IsValid)
    {

    }
    if (fileName == null)
    {

    }

    string destinationPath = Path.Combine(@"C:\", fileName.FileFullName);
    System.IO.File.WriteAllBytes(destinationPath, fileName.Data);
    HttpResponseMessage rm = new HttpResponseMessage();
    rm.StatusCode = HttpStatusCode.OK;
    return rm;
}

【问题讨论】:

    标签: c# asp.net-web-api


    【解决方案1】:

    1.您的控制器应如下所示:

    //For .net core 2.1
    [HttpPost]
    public IActionResult Index(List<IFormFile> files)
    {
        //Do something with the files here. 
        return Ok();
    }
    
    //For previous versions
    
    [HttpPost]
    public IActionResult Index()
    {
        var files = Request.Form.Files;
        //Do something with the files here. 
        return Ok();
    }
    

    2.上传文件也可以使用Multipart content:

            public async Task UploadImageAsync(Stream image, string fileName)
            {
                HttpContent fileStreamContent = new StreamContent(image);
                fileStreamContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data") { Name = "file", FileName = fileName };
                fileStreamContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
                using (var client = new HttpClient())
                using (var formData = new MultipartFormDataContent())
                {
                    formData.Add(fileStreamContent);
                    var response = await client.PostAsync(url, formData);
                    return response.IsSuccessStatusCode;
                }
             }
    

    3.如果您要上传大文件,您应该考虑流式传输文件,您可以阅读here

    【讨论】:

    • 添加 ContentDisposition 和 ContentType,正如您所描述的,最终帮助解决了我的问题。谢谢!
    【解决方案2】:

    恐怕在您尝试检索图像数据之前,一切都会好起来的。

    根据你的问题:

    如何读取图像数据并将其写入文件?

    您要做的就是获取文件的数据及其文件名并将其发送到您的服务。

    我会亲自在双方(客户端和服务端)创建一个UploadedFile 类,包含文件名及其数据,所以:

    public class UploadedFile
    {
        public string FileFullName { get; set; }
        public byte[] Data { get; set; }
    
        public UploadedFile(string filePath)
        {
            FileFullName = Path.GetFileName(Normalize(filePath));
            Data = File.ReadAllBytes(filePath);
        }
    
        private string Normalize(string input)
        {
            return new string(input
                    .Normalize(System.Text.NormalizationForm.FormD)
                    .Replace(" ", string.Empty)
                    .ToCharArray()
                    .Where(c => CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
                    .ToArray());
        }
    }
    

    然后您将需要例如 NewtonSoft 的 JsonConvert 来序列化对象并发送它。

    所以现在您可以异步发送数据了:

    public async Task SendDataAsync(string fullFilePath)
    {
        if (!File.Exists(fullFilePath))
            throw new FileNotFoundException();
        var data = JsonConvert.SerializeObject(new UploadedFile(fullFilePath));
        using (var client = new WebClient())
        {
            client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
            await client.UploadStringTaskAsync(new Uri("http://localhost:64204/api/upload/"), "POST", data);
        }
    }
    

    现在,确保在服务器端正确处理请求。如果由于某种原因参数不匹配,它将不会进入方法(请记住在服务上也有相同的模型/类 - UploadedFile)。

    在服务上,只需更改方法的参数并执行“类似”的操作:

    [HttpPost]
    public HttpResponseMessage Upload(UploadedFile file)
    {
        if (!ModelState.IsValid)
            ...
            
        if (file == null)
            ...
        string destinationPath = Path.Combine(_whateverPath, file.FileFullName);
        File.WriteAllBytes(destinationPath, file.Data);
    }
    

    希望它能帮助您了解该做什么以及您实际上做错了什么。根据我的经验,我已经暴露了类似的东西。

    编辑:我实际上上传了一个双方都工作的示例:一个简单的 .NET Core 控制台应用程序,它检索文件并通过 POST 和一个基本的 WebAPI2 服务发送它一个简单的控制器来检索数据。既准备好了又测试了工作!下载here.

    享受吧。

    【讨论】:

    • 我现在就试一试。感谢您的努力!
    • 现在我有一个 FileNotFoundException。这很有趣。
    • @paulvoelker 你从哪里得到FileNotFoundException?如果您在客户端获取它,请查看您是否将完整文件路径传递给构造函数,或尝试执行 File.Exists(path) 。调试可能会告诉我们。
    • 好吧,我确实检查了这个。我已经从Normalize 中删除了引用,现在我得到了DirectoryNotFoundException。调试有点麻烦,因为我只能在我的物理 iPhone 上测试它。
    • @paulvoelker 继续!我已经更新了我的解决方案以检查文件是否在第一个实例中不存在。祝你好运,我知道它可能看起来比你原来的例子更复杂,但它可以让你上传“任何东西”。如果您最终得到它并发现我的解决方案有帮助,我将不胜感激您将其标记为解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多