如何将任何文件下载到任何设备并查看?

时间:2022-05-16 19:40:21

The below code is an API call in which I'm passing a documentID and I'm trying to open a document. Due to the fact that this whole process is running on a server I'm not able to view the file on any other device(be it another desktop or mobile device) although the file will open up in server machine but wont open locally. Can anyone please guide me through as to where I'm going wrong ? (sorry for the code, I know it might not be perfect as I'm new to web dev. still learning).

下面的代码是一个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);
    }

2 个解决方案

#1


0  

For downloading files from Web API I use a custom FileResult response which inherits from IHttpActionResult, as follows:

为了从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);
    }
}

You can pass in a file path or a stream of bytes depending on what you need.

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

For your particular case you can probably replace Process.Start(localpath); with something like:

对于您的特定情况,您可以替换Process.Start(localpath);有类似的东西:

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

As a consequence you also don't need return Ok(response);. I can't see your action method's signature but it should return an IHttpActionResult or you could specify FileResult directly as the return type if you prefer.

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

(Of course if you have more accurate MIME Type information for your files you should use that instead of "application/octet-stream".)

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

#2


0  

Well what I have done is just returning back the full path of the file from Api to AngularJS controller and I'm using condition

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

if (response.data.message != null) window.open('//'+response.data.message); else alert("File Not Found !");

if(response.data.message!= null)window.open('//'+ response.data.message); else alert(“找不到文件!”);

in the message part the file path is there. This opens the file in a new tab in the web browser. Thank you everyone for your support . learnt a lot.

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

#1


0  

For downloading files from Web API I use a custom FileResult response which inherits from IHttpActionResult, as follows:

为了从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);
    }
}

You can pass in a file path or a stream of bytes depending on what you need.

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

For your particular case you can probably replace Process.Start(localpath); with something like:

对于您的特定情况,您可以替换Process.Start(localpath);有类似的东西:

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

As a consequence you also don't need return Ok(response);. I can't see your action method's signature but it should return an IHttpActionResult or you could specify FileResult directly as the return type if you prefer.

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

(Of course if you have more accurate MIME Type information for your files you should use that instead of "application/octet-stream".)

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

#2


0  

Well what I have done is just returning back the full path of the file from Api to AngularJS controller and I'm using condition

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

if (response.data.message != null) window.open('//'+response.data.message); else alert("File Not Found !");

if(response.data.message!= null)window.open('//'+ response.data.message); else alert(“找不到文件!”);

in the message part the file path is there. This opens the file in a new tab in the web browser. Thank you everyone for your support . learnt a lot.

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