【问题标题】:how to download any file to any device and view?如何将任何文件下载到任何设备并查看?
【发布时间】:2018-08-05 19:59:18
【问题描述】:

下面的代码是一个 API 调用,我在其中传递了一个 documentID 并尝试打开一个文档。由于整个过程都在服务器上运行,因此我无法在任何其他设备(无论是其他台式机还是移动设备)上查看该文件,尽管该文件将在服务器计算机中打开但不会在本地打开。谁能指导我了解我哪里出错了? (对不起代码,我知道它可能并不完美,因为我是网络开发新手。还在学习)。

    {
        int i = 1;
        string key = ConfigurationManager.AppSettings["PhysicalDocumentPath"]; // some address like "xxx.xxx.xxx.xxx\folder\documents...."
        string key2 = ConfigurationManager.AppSettings["PhysicalDocumentPath2"]; // "C:\{somefolder}\{somefolder}...."
        JAppDoc value = new JAppDoc();
        var response = new Response();           
        try
        {
            if (!Directory.Exists(key2))
            {
                Directory.CreateDirectory(key2);
            }

            IAppDataService appDataService = new AppDataService();
            response = appDataService.GetDoc(docId, value);               

            var fileName = value.ApplicantId + "_" + value.DocumentName;
            var savefileName = fileName;
            var fileSavePath = Path.Combine(key, fileName);
            var prevPath = fileSavePath;
            var nextPath = fileSavePath;
            var tmp = fileName.Split('.');
            var tmp1 = tmp[0];                
            while (File.Exists(nextPath))
            {
                tmp = fileName.Split('.');                    
                fileName = tmp1 + i.ToString();
                fileName = fileName + "." + tmp[1];
                savefileName = fileName;                    
                nextPath = Path.Combine(key, savefileName);
                if (File.Exists(nextPath))
                {
                    prevPath = nextPath;
                }
                i++;
            }

            try
            {
                tmp = prevPath.Split(new[] { "Docs\\" }, StringSplitOptions.None);
                var serverpath = key + tmp[1];
                var localpath = key2+ tmp[1];
                if (File.Exists(localpath))
                {
                    Process.Start(localpath);
                }
                else
                {
                    System.IO.File.Copy(serverpath, localpath);
                    Process.Start(localpath);
                }
            }
           catch(Exception e)
            {
                Utils.Write(e);
                response.Message = "File not found !";                    
            }
        }
        catch (Exception ex)
        {
            Utils.Write(ex);
        }

        return Ok(response);
    }

【问题讨论】:

  • 您需要在响应中将文件(或者准确地说,文件的内容)发送回客户端。您可以在 Google 上搜索大量基于 WebAPI 的示例,但使用 FileResult(而不仅仅是简单的 Ok())是一种简单的方法。
  • 调用是通过 AngulaJS 控制器进行的。我能否将 FileResult Response 作为该文件获得?你能多指导一点吗?提前致谢。
  • 您是在进行 ajax 调用还是完整的 HTTP 请求?通过 ajax 下载文件并没有真正起作用,因为它试图将文件内容发送到网页(在 Javascript 变量内),而不是将其作为标准文件下载发送到浏览器。如果您尝试通过 ajax 执行此操作,请考虑提供类似超链接的内容,该链接将在新选项卡中访问下载 URL,或者在需要时通过脚本触发相同的行为。
  • 我通过 angularjs 文件中的完整 HTTP 请求调用它
  • 在这种情况下应该没有问题。当然,您始终可以通过浏览器或 PostMan 等其他工具请求单独测试您的 Web API 端点。然后你开始测试真正调用它的客户端代码。

标签: asp.net angularjs asp.net-mvc


【解决方案1】:

为了从 Web API 下载文件,我使用继承自 IHttpActionResult 的自定义 FileResult 响应,如下所示:

/// <summary>
/// Http Action Result containing the requested document
/// </summary>
public class FileResult : IHttpActionResult
{
    private readonly string filePath;
    private readonly string contentType;
    private readonly byte[] content;
    private readonly string fileName;

    /// <summary>
    /// Initialise the action result with the path to the file and the content type. The contents of the file will be read.
    /// </summary>
    /// <param name="FilePath">Path to the file to read</param>
    /// <param name="ContentType">Type of content</param>
    public FileResult(string FilePath, string ContentType = null)
    {
        filePath = FilePath;
        fileName = Path.GetFileName(FilePath);
        contentType = ContentType;
    }

    /// <summary>
    /// Initialise the action result with the contents of the file, it's filename and the content type.
    /// </summary>
    /// <param name="Content"></param>
    /// <param name="FileName"></param>
    /// <param name="ContentType"></param>
    public FileResult(byte[] Content, string FileName, string ContentType)
    {
        content = Content;
        fileName = FileName;
        contentType = ContentType;
    }

    /// <summary>
    /// Creates an System.Net.Http.HttpResponseMessage asynchronously.
    /// </summary>
    /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
    /// <returns>A task that, when completed, contains the System.Net.Http.HttpResponseMessage.</returns>
    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        return Task.Run(() =>
        {
            HttpContent output;
            if (filePath != null)
            {
                output = new StreamContent(File.OpenRead(filePath));
            }
            else
            {
                output = new StreamContent(new MemoryStream(content));
            }

            var response = new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = output
            };

            var mappedContentType = contentType ?? MimeMapping.GetMimeMapping(Path.GetExtension(filePath));
            response.Content.Headers.ContentType = new MediaTypeHeaderValue(mappedContentType);
            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
            response.Content.Headers.ContentDisposition.FileName = fileName;

            return response;
        }, cancellationToken);
    }
}

您可以根据需要传入文件路径或字节流。

对于您的特定情况,您可以将Process.Start(localpath); 替换为:

return new FileResult(localpath, fileName, "application/octet-stream");

因此,您也不需要return Ok(response);。我看不到你的操作方法的签名,但它应该返回一个IHttpActionResult,或者如果你愿意,你可以直接指定FileResult作为返回类型。

(当然,如果您的文件有更准确的 MIME 类型信息,您应该使用它而不是“application/octet-stream”。)

【讨论】:

  • 很抱歉,我现在检查了一下,好像我正在使用 angularJS 进行 ajax 调用。 Method.postObj("applicant/document", docdetails).then(function (response) { $("#uploadDialog").ejDialog("close"); Method.getbyId("applicant/document/app
  • this.post = function (path, param) { var request = $http({ method: "post", url: appSetting.apiBaseUrl + path + "/", dataType: 'json.. ....................
  • 嗯,这与 Web API / C# 解决方案无关,这是您要求的,如果您使用常规 HTTP 请求,它可以正常工作。我建议您采用另一种方法来处理主要问题的 cmets。同时,您可以在实现 JS 之前单独测试 API 部分以确保其按预期工作。
  • 好的,您能指导我如何在服务器上将文件转换为 HTML,以便用户可以在任何情况下查看该文件吗?目前对用户可以查看的文件类型没有限制。它可以是文本、图像等任何内容。或者只是如何下载文件以便用户可以根据自己的选择打开它?
  • 不确定转换为 HTML 是什么意思?你的意思是嵌入网页?并非所有内容都可以嵌入网页中,主要是图像 TBH。现在,上面的代码已经允许用户下载文件并以他们喜欢的方式查看它。他们只需要对该操作方法发出有效的 HTTP 请求
【解决方案2】:

我所做的只是将文件的完整路径从 Api 返回到 AngularJS 控制器,我正在使用条件

如果 (response.data.message != null) window.open('//'+response.data.message); 别的 alert("找不到文件!");

在消息部分,文件路径在那里。 这将在 Web 浏览器的新选项卡中打开文件。谢谢大家的支持 。学到了很多。

【讨论】:

    猜你喜欢
    • 2014-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-20
    相关资源
    最近更新 更多