简体   繁体   English

上传到 Dropbox 时出错

[英]Getting an error when uploading to Dropbox

I am attempting to upload a file to dropbox.我正在尝试将文件上传到 Dropbox。

Here is what I have said so far:这是我到目前为止所说的:

    using (var stream = new MemoryStream(File.ReadAllBytes(fileName)))
    {
      var numChunks = (int) Math.Ceiling((double) stream.Length / chunkSize);
      var buffer = new byte[chunkSize];
      string sessionId = null;

      if (numChunks == 1)
      {
        using (var memStream = new MemoryStream(buffer, 0, chunkSize))
        {
          Console.WriteLine($"Sending file: {path}");
          var tst = await client.Files.UploadAsync(path, WriteMode.Overwrite.Instance, body: memStream);
        }
      }
      else
      {
        for (var idx = 0; idx < numChunks; idx++)
        {
          Console.WriteLine($"Uploading chunk {idx + 1} / {numChunks}.");
          var byteRead = stream.Read(buffer, 0, chunkSize);

          using (var memStream = new MemoryStream(buffer, 0, byteRead))
          {
            if (idx == 0)
            {
              var result = await client.Files.UploadSessionStartAsync(body: memStream);
              sessionId = result.SessionId;
            }

            var cursor = new UploadSessionCursor(sessionId, (ulong) (chunkSize * idx));

            if (idx == numChunks - 1)
            {
              Console.WriteLine($"Finalizing file: {path}");
              var response = await client.Files.UploadSessionFinishAsync(cursor, new CommitInfo(path), memStream);
            }
            else
            {
              await client.Files.UploadSessionAppendV2Async(cursor, body: memStream);
            }
          }
        }
      }

      var url = string.Empty;
      var link = await client.Sharing.ListSharedLinksAsync(path);

      if (link.Links.Count == 0)
      {
        var result = await client.Sharing.CreateSharedLinkWithSettingsAsync(path);
        url = result.Url;
      }
      else
      {
        url = link.Links[0].Url;
      }

      Console.WriteLine();
      Console.WriteLine("Dropbox Download Link:");
      Console.WriteLine(url);
      Console.WriteLine();
      //Console.ReadKey();
    }

When I try to send up a large file, I'm getting this message:当我尝试发送一个大文件时,我收到以下消息:

在此处输入图片说明

I'm accounting for small and large files.我正在考虑小文件和大文件。 If the file is bigger than the chunksize.如果文件大于块大小。 I cannot get it to send up the file, I just get an error.我无法让它发送文件,我只是收到一个错误。

It's happening at this line:它发生在这一行:

var response = await client.Files.UploadSessionFinishAsync(cursor, new CommitInfo(path), memStream);

Any suggestions?有什么建议?

For the first chunk idx==0 you have to call only UploadSessionStartAsync and you also call UploadSessionAppendV2Async .对于第一个块idx==0你只需要调用UploadSessionStartAsync并且你还调用UploadSessionAppendV2Async Try this:尝试这个:

...
using (var memStream = new MemoryStream(buffer, 0, byteRead))
{
    if (idx == 0)
    {
        var result = await client.Files.UploadSessionStartAsync(body: memStream);
          sessionId = result.SessionId;
    }
    else
    {
        var cursor = new UploadSessionCursor(sessionId, (ulong) (chunkSize * idx));

        if (idx == numChunks - 1)
        {
          Console.WriteLine($"Finalizing file: {path}");
          var response = await client.Files.UploadSessionFinishAsync(cursor, new CommitInfo(path), memStream);
        }
        else
        {
          await client.Files.UploadSessionAppendV2Async(cursor, body: memStream);
        }
    }
}
...

Didn't run it locally and didn't use Dropbox's client but I see the following...没有在本地运行它,也没有使用 Dropbox 的客户端,但我看到以下内容......

  1. Probably, while slow manual debugs you can miss the issue.可能,虽然手动调试缓慢,但您可能会错过这个问题。
  2. Expect, that the error message is slightly misleading.期望,错误消息有点误导。 In general, it is right.一般来说,这是正确的。 But there should be an additional check to catch a case when your original Stream was changed .但是当您的原始 Stream 被更改时,应该有一个额外的检查来捕捉情况。
  3. Let me add more sync/async chaos data about 'what the hell is happening here?!.'.让我添加更多关于“这里到底发生了什么?!.”的同步/异步混沌数据。 At first, your for runs synchronously - all upload sessions start in parallel in a short period of time.首先,您的for同步运行 - 所有上传会话在短时间内并行启动。 At second, each of for s has its own block-level scope that has the using (...) {...} syntax sugar in the sync context.其次,每个for s 都有自己的block-level scope ,在同步上下文中具有using (...) {...}语法糖。 All var memStream s are covering each other in the upper sync context.所有var memStream都在上层同步上下文中相互覆盖。 Then, every thread does its work in its own async context.然后,每个线程在它自己的异步上下文中完成它的工作。 Take a look at the var response .看看var response It is a loop variable and it is not in use in your main SYNC context.它是一个循环变量,不在您的主 SYNC 上下文中使用。 It is not declared out of the using closure.它不是从using闭包中声明的。 So this line can be not awaitable in the sync context.所以这一行在同步上下文中是不可等待的。 In this case using will finish when the memStream will be consumed but UploadSessionFinishAsync will be working still.在这种情况下, using将在memStream被消耗时完成,但UploadSessionFinishAsync将继续工作。
  4. Why it happens only at var response = await client.Files.UploadSessionFinishAsync(cursor, new CommitInfo(path), memStream);为什么它只发生在var response = await client.Files.UploadSessionFinishAsync(cursor, new CommitInfo(path), memStream); ? ? Think, it could be the issue in each await client.Files... call but only client.Files.UploadSessionFinishAsync tries to do something with the passed memStream .想想,这可能是每个await client.Files...调用中的问题,但只有client.Files.UploadSessionFinishAsync尝试对传递的memStream做一些事情。 For example, close it as a final step.例如,将其作为最后一步关闭。 Or process the memStream , abandoned the stream, do another work such as a request to Dropbox to get a final upload result.或者处理memStream ,放弃流,做其他的工作,比如请求 Dropbox 得到最终的上传结果。
  5. Idea about the fix.关于修复的想法。 I think you need to declare the final result var response above the for scope.我认为您需要在for范围之上声明最终结果var response Then just set the result at the last chunk processing.然后只需在最后一个块处理时设置结果。 In this case using will have to wait for its result, only then it could dispose memStream .在这种情况下using将不得不等待它的结果,只有这样它才能处理memStream Just like with sessionId = result.SessionId;就像sessionId = result.SessionId; . . Or just explicitly wait for its result before the using end.或者只是在using结束之前明确等待其结果。
  6. Code optimization.代码优化。 For a short file you don't need buffer and sessionId .对于短文件,您不需要buffersessionId They are for multiple uploading threads.它们用于多个上传线程。 For a big file - return the UploadSessionFinishAsync result from your loop.对于大文件 - 从循环中返回UploadSessionFinishAsync结果。 Maybe, declare multiple memStream s as different vars.也许,将多个memStream声明为不同的变量。 Not sure about UploadSessionAppendV2Async result.不确定UploadSessionAppendV2Async结果。 If it is void then it is OK.如果它是void那么就可以了。 Otherwise, such a result also should be awaited.否则,也应该等待这样的结果。 It could be like this:它可能是这样的:
//outer vars
SomeDropboxFileUploadResultOrElse uploadResult;
string sessionId = null;

//original full file read
using (var stream = new MemoryStream(File.ReadAllBytes(fileName)))
{
   var numChunks = (int) Math.Ceiling((double) stream.Length / chunkSize);
   if (numChunks == 1)
   {
       Console.WriteLine($"Sending file: {path}");
       uploadResult = await client.Files.UploadAsync(path, WriteMode.Overwrite.Instance, body: stream);
   }
   else
   {
       var buffer = new byte[chunkSize];
       for (var idx = 0; idx < numChunks; idx++)
       {
           Console.WriteLine($"Uploading chunk {idx + 1} / {numChunks}.");
           var byteRead = stream.Read(buffer, 0, chunkSize);

           using (var memStream = new MemoryStream(buffer, 0, byteRead))
           {
               if (idx == 0)
               {
                   var result = await client.Files.UploadSessionStartAsync(body: memStream);
                   sessionId = result.SessionId;
               }
               //prevent 2+ parts processing on idx == 0 iteration, start thread in the sync scope but wait for sessionId value in the async thread
               else
               {
                   var cursor = new UploadSessionCursor(sessionId, (ulong)(chunkSize * idx));
                   if (idx == numChunks - 1)
                   {
                       Console.WriteLine($"Finalizing file: {path}");
                       //explicitly pass result to outer scope, then the execution could be continued, memStream could be closed below
                       uploadResult = await client.Files.UploadSessionFinishAsync(cursor, new CommitInfo(path), memStream);
                   }
                   else
                   {
                       await client.Files.UploadSessionAppendV2Async(cursor, body: memStream);
                   }
               }
           } //memStream?.Dispose(); 
       }
   }
...
}

Hope, this will help.希望,这会有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM