首页 > 解决方案 > 为什么 Google Drive 返回“无法解析 Content-Range 标头。”?

问题描述

这是我用于恢复(可能)中断上传到 Google 云端硬盘的简单酒窝代码:

Using message = New ByteArrayContent(New Byte() {})
        message.Headers.ContentRange = New Headers.ContentRangeHeaderValue(Session.Size)
        'message.Headers.TryAddWithoutValidation("Content-Range", "bytes */*")
        Dim response = Await PutAsync("https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&upload_id=" & Session.Code, message)
        Dim msg = Await response.Content.ReadAsStringAsync
        'ERR: this is always 'Failed to parse Content-Range header.'
        Dim position = 0L
        If response.Headers.Contains("Range") Then
            Dim range = response.Headers.GetValues("Range")
            position = range.First.SplitPlus("-")(1)
        End If

但谷歌不断回归

无法解析 Content-Range 标头。

我手动检查了标题,似乎没问题:

Content-Range: bytes */389587456
Content-Length: 0

可能是什么问题?

我尝试了什么:

使用StringContent代替ByteArrayContent

TryAddWithoutValidation_*/*

都不工作

满怀期待,

更新

我尝试从头开始上传新文件。新鲜上传。这是代码:

If response.StatusCode = 308 Then
            Using fileStream = New ThrottledFileStream(Session.FilePath)
                fileStream.Position = position
                Using Content = New StreamContent(fileStream)
                    Content.Headers.ContentRange = New Headers.ContentRangeHeaderValue(position, Session.Size, Session.Size)
                    Using Timer = New Timer(Sub(o)
                                                Dim ps As Long
                                                If fileStream.CanRead Then ps = fileStream.Position
                                                Progress.Invoke(New CloudUploadState With {.Response = response, .Position = ps})
                                            End Sub, Nothing, 0, 20000)
                        Dim finishResponse = Await Put("https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&upload_id=" & Session.Code, Content)
                        Progress.Invoke(New CloudUploadState With {.Response = finishResponse})
                    End Using
                End Using
            End Using
        End If

但我得到了完全相同的回应:Failed to parse Content-Range header.

这是在整个文件上传之后(基于返回所需的时间,以及文件流的位置)

我的要求有什么问题?

谢谢

为了完整起见,这里基本上是整个代码。我将不胜感激任何帮助或指示:

    Public Async Function Upload(Session As DriveSession, Progress As Action(Of CloudUploadState)) As Task Implements ICloudStorage.Upload
    Await EnsureCredentials()
    If Session.Code Is Nothing Then
        Dim path = Session.FilePath
        If Debugger.IsAttached Then path = IO.Path.Combine("Test", path.Replace("\\", "\").Replace(":", ""))
        Dim currentFolderId = ""
        For Each nextFolderName In path.Split("\")
            Dim url = $"https://www.googleapis.com/drive/v3/files?fields=files(name,id)&q=name='{nextFolderName}'"
            If currentFolderId <> "" Then url &= $" and '{currentFolderId}' in parents"
            If path.EndsWith("\" & nextFolderName) Then
                Dim metadata = New JObject From {{"name", IO.Path.GetFileName(path)}}
                metadata("parents") = New JArray From {currentFolderId}
                Using message = New StringContent(metadata.ToString, Encoding.UTF8, "application/json")
                    message.Headers.Add("X-Upload-Content-Type", GetExtMime(IO.Path.GetExtension(path).LeftCut(".")))
                    message.Headers.Add("X-Upload-Content-Length", Session.Size)
                    Dim response = Await Post($"https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable", message)
                    Session.Code = response.Headers.Location.QueryParams("upload_id")
                    Using d = GetSystemContext(True)
                        Dim ds = d.Find(Of DriveSession)(Session.ID)
                        ds.Code = Session.Code
                        d.SaveChanges()
                    End Using
                End Using
                'End If
            Else
                url &= " and mimeType = 'application/vnd.google-apps.folder'"
                Dim ret = Await GetString(url)
                Dim files = ParseResponse(ret)
                If files.Count > 1 Then DevError("identical names")
                If files.Any Then
                    currentFolderId = files.First.Id
                Else
                    Dim data = New JObject From {{"name", nextFolderName}, {"mimeType", "application/vnd.google-apps.folder"}}
                    If currentFolderId IsNot Nothing Then data.Add(New JProperty("parents", New JArray(currentFolderId)))
                    Using content = New StringContent(data.ToString, Encoding.UTF8, "application/json")
                        Using response = Await Post("https://www.googleapis.com/drive/v3/files", content)
                            Dim message = Await response.Content.ReadAsStringAsync
                            currentFolderId = JObject.Parse(message).Value(Of String)("id")
                        End Using
                    End Using
                End If
            End If
        Next
    End If

    Using message = New ByteArrayContent(New Byte() {})
        message.Headers.ContentRange = New Headers.ContentRangeHeaderValue(Session.Size)
        Dim response = Await PutAsync("https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&upload_id=" & Session.Code, message)
        Dim position = 0L
        If response.Headers.Contains("Range") Then
            Dim range = response.Headers.GetValues("Range")
            position = range.First.SplitPlus("-")(1)
        End If
        Progress.Invoke(New CloudUploadState With {.Response = response, .Position = position})
        If response.StatusCode = 308 Then
            Using fileStream = New ThrottledFileStream(Session.FilePath)
                fileStream.Position = position
                Using Content = New StreamContent(fileStream)
                    Content.Headers.ContentRange = New Headers.ContentRangeHeaderValue(position, Session.Size, Session.Size)
                    Using Timer = New Timer(Sub(o)
                                                Dim ps As Long
                                                If fileStream.CanRead Then ps = fileStream.Position
                                                Progress.Invoke(New CloudUploadState With {.Response = response, .Position = ps})
                                            End Sub, Nothing, 0, 30000)
                        Dim finishResponse = Await PutAsync("https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&upload_id=" & Session.Code, Content)
                        Progress.Invoke(New CloudUploadState With {.Response = finishResponse})
                    End Using
                End Using
            End Using
        End If
    End Using
End Function

标签: google-drive-apidotnet-httpclient

解决方案


好的。知道了。请求中缺少“内容长度:0”


推荐阅读