【问题标题】:How can I tell if a file with this name exists?如何判断具有此名称的文件是否存在?
【发布时间】:2014-05-23 00:02:29
【问题描述】:

在写入 GCS 文件之前,我想测试它是否存在。但是,我从file.Stat 收到一个错误,它在os.IsNotExist 中返回false,并且我在appengine/fileappengine 中看不到任何可以测试的导出错误。从 App Engine 确定 GCS 中不存在文件的最佳方法是什么?

我也可能以完全错误的方式执行此操作,并且还有其他方法可以确保我不会覆盖或附加到现有文件。如果有的话,我也很想听听。

我的复制代码:

package main

import (
    "net/http"
    "fmt"

    "appengine"
    "appengine/file"
)

func init() {
    http.HandleFunc("/test", reproduceHandler)
}

func reproduceHandler(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    // You'll need your own bucket name here
    _, err := file.Stat(c, "/gs/my-bucket-name/my-file-name")
    fmt.Fprintln(w, err)
}

当我访问“/test”时显示如下:

API error 100 (file: EXISTENCE_ERROR)

【问题讨论】:

  • 文档没有说太多。如果文件存在与否,Stat 应该返回。
  • Stat 返回一个os.FileInfo 和一个error。在这种情况下,os.FileInfo<nil>error 与我的问题一样。诀窍是消除该错误与 Stat 可能返回的任何其他错误的歧义。
  • 看源码:code.google.com/p/appengine-go/source/browse/appengine/file/… 貌似文件不存在总是会失败,因为实现的开放限制。如果文件存在,那么它将能够返回一个统计对象。
  • 但是如果文件存在,但是由于其他原因打开失败怎么办?看起来在这种情况下,Stat 将返回nil, err,因此设置err 不足以说明该文件不存在。
  • 你想达到什么目的?使用Object Preconditions 可能会更好。例如,将if-generation-match 设置为 0 只会在对象不存在时写入。

标签: google-app-engine go google-cloud-storage


【解决方案1】:

在此处查看 appengine 如何定义文件错误:

https://code.google.com/p/appengine-go/source/browse/appengine_internal/files/file_service.pb.go

您应该能够根据文件中的枚举顶部识别错误类型:

FileServiceErrors_OK                                 FileServiceErrors_ErrorCode = 0
FileServiceErrors_API_TEMPORARILY_UNAVAILABLE        FileServiceErrors_ErrorCode = 1
FileServiceErrors_REQUEST_TOO_LARGE                  FileServiceErrors_ErrorCode = 3
FileServiceErrors_RESPONSE_TOO_LARGE                 FileServiceErrors_ErrorCode = 4
FileServiceErrors_INVALID_FILE_NAME                  FileServiceErrors_ErrorCode = 5
FileServiceErrors_OPERATION_NOT_SUPPORTED            FileServiceErrors_ErrorCode = 6
FileServiceErrors_IO_ERROR                           FileServiceErrors_ErrorCode = 7
FileServiceErrors_PERMISSION_DENIED                  FileServiceErrors_ErrorCode = 8
FileServiceErrors_WRONG_CONTENT_TYPE                 FileServiceErrors_ErrorCode = 9
FileServiceErrors_FILE_NOT_OPENED                    FileServiceErrors_ErrorCode = 10
FileServiceErrors_WRONG_OPEN_MODE                    FileServiceErrors_ErrorCode = 11
FileServiceErrors_EXCLUSIVE_LOCK_REQUIRED            FileServiceErrors_ErrorCode = 12
FileServiceErrors_FILE_TEMPORARILY_UNAVAILABLE       FileServiceErrors_ErrorCode = 13
FileServiceErrors_EXISTENCE_ERROR                    FileServiceErrors_ErrorCode = 100
FileServiceErrors_FINALIZATION_ERROR                 FileServiceErrors_ErrorCode = 101
FileServiceErrors_UNSUPPORTED_CONTENT_TYPE           FileServiceErrors_ErrorCode = 102
FileServiceErrors_READ_ONLY                          FileServiceErrors_ErrorCode = 103
FileServiceErrors_EXCLUSIVE_LOCK_FAILED              FileServiceErrors_ErrorCode = 104
FileServiceErrors_EXISTENCE_ERROR_METADATA_NOT_FOUND FileServiceErrors_ErrorCode = 105
FileServiceErrors_EXISTENCE_ERROR_METADATA_FOUND     FileServiceErrors_ErrorCode = 106
FileServiceErrors_EXISTENCE_ERROR_SHARDING_MISMATCH  FileServiceErrors_ErrorCode = 107
FileServiceErrors_FINALIZATION_IN_PROGRESS           FileServiceErrors_ErrorCode = 108
FileServiceErrors_EXISTENCE_ERROR_OBJECT_NOT_FOUND   FileServiceErrors_ErrorCode = 109
FileServiceErrors_EXISTENCE_ERROR_BUCKET_NOT_FOUND   FileServiceErrors_ErrorCode = 110
FileServiceErrors_SEQUENCE_KEY_OUT_OF_ORDER          FileServiceErrors_ErrorCode = 300
FileServiceErrors_OUT_OF_BOUNDS                      FileServiceErrors_ErrorCode = 500
FileServiceErrors_GLOBS_NOT_SUPPORTED                FileServiceErrors_ErrorCode = 600
FileServiceErrors_FILE_NAME_NOT_SPECIFIED            FileServiceErrors_ErrorCode = 701
FileServiceErrors_FILE_NAME_SPECIFIED                FileServiceErrors_ErrorCode = 702
FileServiceErrors_FILE_ALREADY_EXISTS                FileServiceErrors_ErrorCode = 703
FileServiceErrors_UNSUPPORTED_FILE_SYSTEM            FileServiceErrors_ErrorCode = 704
FileServiceErrors_INVALID_PARAMETER                  FileServiceErrors_ErrorCode = 705
FileServiceErrors_SHUFFLER_INTERNAL_ERROR            FileServiceErrors_ErrorCode = 800
FileServiceErrors_SHUFFLE_REQUEST_TOO_LARGE          FileServiceErrors_ErrorCode = 801
FileServiceErrors_DUPLICATE_SHUFFLE_NAME             FileServiceErrors_ErrorCode = 802
FileServiceErrors_SHUFFLE_NOT_AVAILABLE              FileServiceErrors_ErrorCode = 803
FileServiceErrors_SHUFFLER_TEMPORARILY_UNAVAILABLE   FileServiceErrors_ErrorCode = 900
FileServiceErrors_MAX_ERROR_CODE                     FileServiceErrors_ErrorCode = 9999

您遇到的错误很可能是 FileServiceErrors_ErrorCode 类型(或指向该类型的指针),因此请使用类型断言检查并比较您想要识别的情况:

_, err := file.Stat(c, "/gs/my-bucket-name/my-file-name")

if apiErr, ok := err.(*appengine_internal.APIError); ok {
    if apiErr.Code == int32(files.FileServiceErrors_EXISTENCE_ERROR) && apiErr.Service == "file" {
        // file does not exist
    }
}

别忘了

import "appengine_internal"
import "appengine_internal/files"

【讨论】:

  • 完美!感谢您进行编辑以添加详细信息。在编辑之前我不太确定如何执行此操作,但现在非常清楚。
  • 其实我还在摸索,不过这告诉我files.FileServiceErrors_ErrorCode没有实现错误(缺少Error方法)。
  • 原来错误的类型是*appengine_internal.APIError,它有一个Code属性设置为(在这种情况下)files.FileServiceErrors_ErrorCode。我已经编辑了您的答案,以便在示例解决方案中考虑到这一点。
猜你喜欢
  • 1970-01-01
  • 2011-07-14
  • 2015-11-15
  • 1970-01-01
  • 1970-01-01
  • 2010-09-17
  • 2010-12-11
  • 2013-05-12
  • 2015-09-25
相关资源
最近更新 更多