【问题标题】:how to call web api to download document to website directory using webclient如何使用 webclient 调用 web api 将文档下载到网站目录
【发布时间】:2018-01-29 18:16:18
【问题描述】:

我正在努力使用基于从 WebAPI 返回的字节数组的数据创建文件。以下是我调用 web api 的代码

 using (var http = new WebClient())
            {
                string url = string.Format("{0}api/FileUpload/FileServe?FileID=" + fileID, webApiUrl);
                http.Headers[HttpRequestHeader.ContentType] = "application/octet-stream";
                http.Headers[HttpRequestHeader.Authorization] = "Bearer " + authCookie.Value;
                http.DownloadDataCompleted += Http_DownloadDataCompleted;
                byte[] json = await http.DownloadDataTaskAsync(url);



            }

api代码是

[HttpGet]
    [Route("FileServe")]
    [Authorize(Roles = "Admin,SuperAdmin,Contractor")]
    public async Task<HttpResponseMessage> GetFile(int FileID)
    {
        using (var repo = new MBHDocRepository())
        {
            var file = await repo.GetSpecificFile(FileID);
            if (file == null)
            {
                throw new HttpResponseException(HttpStatusCode.BadRequest);
            }

            var stream = File.Open(file.PathLocator, FileMode.Open);
            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
            response.Content = new StreamContent(stream);
            response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(file.FileType);
            return response;
        }
    }

我收到一个字节数组作为响应,但是我无法从该字节数组创建相应的文件。我不知道如何将字节数组转换为相关的文件类型(例如 jpg 或基于 web api 中文件类型的 pdf)。任何帮助将不胜感激。

【问题讨论】:

  • 所以你在字段 json 中有一个字节数组,是你的文件,但你不明白如何保存该文件?比如你发了一张png格式的图片,那个字节数组就是图片,你要保存到硬盘吗?
  • 网站和 web api 位于两个不同的端点上,因此我想从 web api 通过网站下载文档并将其保存到文件夹中。希望你明白我的意思
  • stackoverflow.com/a/6397249/5947043 向您展示如何将字节数组保存到文件中。您可能只需要从标头中读取 MIME 类型来决定为其提供什么扩展名。不知道您为什么将变量命名为 json,因为显然不是。
  • 变量“byte[] json”只是一个名字,反馈应该以字节为单位
  • 嗯,我认为你在 WebClient 上使用了错误的方法,像 OpenRead 这样的东西呢,它返回一个流,然后你可以查看结果并找到它的 mime 类型

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


【解决方案1】:

好的,首先有几种方法可以解决您的问题,在服务器端,您可以简单地发送内容类型并将其保留,或者您也可以发送完整的文件名,这会进一步帮助您。

我已使用基本测试代码删除了特定于您的内容的代码,请忽略这些内容并根据您的代码使用它。

这里有一些设计说明:

            [HttpGet]
            [Route("FileServe")]
            [Authorize(Roles = "Admin,SuperAdmin,Contractor")]
            public async Task<HttpResponseMessage> GetFileAsync(int FileID) //<-- If your method returns Task have it be named with Async in it
            {
                using (var repo = new MBHDocRepository())
                {
                    var file = await repo.GetSpecificFile(FileID);
                    if (file == null)
                    {
                      throw new HttpResponseException(HttpStatusCode.BadRequest);
                    }

            var stream = File.Open(file.PathLocator, FileMode.Open);
            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
            response.Content = new StreamContent(stream);
            response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(file.FileType);
            response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName=Path.GetFileName(file.PathLocator)};
            return response;
                }
            }

您的客户端代码在这里有两个选项:

static void Main(string[] args)
        {
            using (var http = new WebClient())
            {


    string url = string.Format("{0}api/FileUpload/FileServe?FileID={1}",webApiUrl, fileId);
http.Headers[HttpRequestHeader.ContentType] = "application/octet-stream";
                http.Headers[HttpRequestHeader.Authorization] = "Bearer " + authCookie.Value;
                var response = http.OpenRead(url);
                var fs = new FileStream(String.Format(@"C:\Users\Bailey Miller\Downloads\{0}", GetName(http.ResponseHeaders)), FileMode.Create);
                response.CopyTo(fs); <-- how to move the stream to the actual file, this is not perfect and there are a lot of better examples

            fs.Flush();
            fs.Close();
            }


        }

        private static object GetName(WebHeaderCollection responseHeaders)
        {

            var c_type = responseHeaders.GetValues("Content-Type"); //<-- do a switch on this and return a really weird file name with the correct extension for the mime type.
        var cd = responseHeaders.GetValues("Content-Disposition")[0].Replace("\"", ""); <-- this gets the attachment type and filename param, also removes illegal character " from filename if present
        return cd.Substring(cd.IndexOf("=")+1); <-- extracts the file name
        }

【讨论】:

  • @WadeMartin 我认为这将为您解决问题。可以清理文件保存代码以获得更异步的方式,并且可以将其移动到不同的线程以获得更好的性能。但这为您提供了两种选择,确定文件名客户端并根据 mime 类型添加扩展名,或者从服务器获取文件名并让服务器处理它。
  • "responseHeaders.GetValues("Content-Type");"此语句返回一个 json 对象。由于响应,我无法创建正确类型的对象
  • 然后在return response处设置一个断点,看看file.FileType的值是多少。如果它设置为application/json,那是有道理的。 file.PathLocator 长什么样子?
  • 所以`responseHeaders.GetValues("Content-Type")[0] 返回一个对象?不是字符串?
  • web api 方法似乎没有正确运行,因为我似乎无法在该方法上放置任何断点。 OpenRead 方法没有到达我的断点
猜你喜欢
  • 1970-01-01
  • 2011-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多