【问题标题】:c# webClient.DownloadFile doesn't download, it just creates an empty text filec# webClient.DownloadFile 不下载,它只是创建一个空文本文件
【发布时间】:2018-02-09 21:16:25
【问题描述】:

我想将 Pastebin(raw) 中的文本下载到 texfile 中。 我创建了一个IEnumerator,但不知何故它只是创建了一个空文本文件。

public IEnumerator DownloadTextFile()
{
    WebClient version = new WebClient();
    yield return version;
    version.DownloadFileAsync(new Uri(myLink), "version.txt");
}

public IEnumerator DownloadTextFile()
{
    WebClient version = new WebClient();
    yield return version;
    version.DownloadFile(myLink , "version.txt");
}

提前致谢。

【问题讨论】:

    标签: c# unity3d download webclient pastebin


    【解决方案1】:

    Scott Chamberlain 的 solution 是在 Unity 中执行此操作的正确推荐方式,因为 WWW API 在后台处理线程问题。您只需使用协程下载它,然后使用 Scott 提到的 File.WriteAllXXX 函数之一手动保存它。

    我添加此答案是因为该问题专门询问WebClient,并且有时使用WebClient 很好,例如大数据。

    问题是你正在屈服WebClient。您不必像以前那样在协程中产生 WebClient。只需订阅其DownloadFileCompleted 事件,该事件将在另一个线程上调用。为了在DownloadFileCompleted回调函数中使用Unity函数,您必须使用this post中的UnityThread脚本并在UnityThread.executeInUpdate函数的帮助下执行Unity函数..

    这是一个完整的例子(需要UnityThread):

    public Text text;
    int fileID = 0;
    
    void Awake()
    {
        UnityThread.initUnityThread();
    }
    
    void Start()
    {
        string url = "http://www.sample-videos.com/text/Sample-text-file-10kb.txt";
        string savePath = Path.Combine(Application.dataPath, "file.txt");
    
        downloadFile(url, savePath);
    }
    
    void downloadFile(string fileUrl, string savePath)
    {
        WebClient webClient = new WebClient();
        webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DoSomethingOnFinish);
        webClient.QueryString.Add("fileName", fileID.ToString());
        Uri uri = new Uri(fileUrl);
        webClient.DownloadFileAsync(uri, savePath);
        fileID++;
    }
    
    //THIS FUNCTION IS CALLED IN ANOTHER THREAD BY WebClient when download is complete
    void DoSomethingOnFinish(object sender, AsyncCompletedEventArgs e)
    {
        string myFileNameID = ((System.Net.WebClient)(sender)).QueryString["fileName"];
        Debug.Log("Done downloading file: " + myFileNameID);
    
        //Ssafety use Unity's API in another Thread with the help of UnityThread
        UnityThread.executeInUpdate(() =>
        {
            text.text = "Done downloading file: " + myFileNameID;
        });
    }
    

    【讨论】:

      【解决方案2】:

      WebClient 不是为像这样在 Unity3D 中使用而设计的,yield return version; 不会等待文件被下载。

      您可以做的是使用WWW 类并以这种方式执行下载。 WWW 是 Unity 的一部分,旨在按照 Unity 的工作方式工作。

      public IEnumerator DownloadTextFile()
      {
         WWW version = new WWW(myLink);
         yield return version;
         File.WriteAllBytes("version.txt", version.bytes);
      
         //Or if you just wanted the text in your game instead of a file
         someTextObject.text = version.text;
      }
      

      一定要通过调用StartCoroutine(DownloadTextFile())来启动DownloadTextFile

      【讨论】:

      • 感谢您快速且非常有帮助的回复。效果很好。
      • 有没有办法查看下载进度?
      • 是的,如果您查看 WWW 的文档,您会看到 progress 字段。阅读以了解进展情况。
      【解决方案3】:

      确保将 WebClient 放在 using 语句中,以便它可以正确处理并确保下载完成。对于 Async 版本,您需要确保您不会在忙碌时放弃。

              //Method 1
              using (var version = new WebClient())
                  version.DownloadFile("https://pastebin.com/raw/c1GrSCKR", @"c:\temp\version.txt");
      
              // Method 2 (better if you are working within Task based async system)
              //using (var version = new WebClient())
              //    await version.DownloadFileTaskAsync("https://pastebin.com/raw/c1GrSCKR", @"c:\temp\version.txt");
      
              // Method 3 - you can't dispose till is completed / you can also register to get notified when download is done.
              using (var version = new WebClient())
              {
                  //version.DownloadFileCompleted += (object sender, AsyncCompletedEventArgs e) =>
                  //{
      
                  //};
                  version.DownloadFileAsync(new Uri("https://pastebin.com/raw/c1GrSCKR"), @"c:\temp\version.txt");
      
                  while (version.IsBusy) {  }
              }
      

      【讨论】:

      • 注意,这是 Unity3d,所以while (version.IsBusy) { } 是一个很大的禁忌,会锁定游戏。你应该改用while (version.IsBusy) { yield return 0; },这样它会等待一帧并再次检查它是否正忙。
      • 很好,斯科特。我完全忽略了 Unity 部分。你的帖子很到位。
      猜你喜欢
      • 2012-03-12
      • 1970-01-01
      • 2022-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-19
      • 2011-12-07
      • 2019-08-23
      相关资源
      最近更新 更多