LEATH
正如@yumaikas 所说,不推荐使用Files API。如果此数据来自某种用户上传,您应该修改上传表单以使用 Blobstore 上传 URL(特别是,将编码设置为multipart/form-dataormultipart/mixed并命名所有文件上传字段file,除了您不想的那些存储在 blobstore 中)。但是,如果这是不可能的(例如,您无法控制用户输入,或者您必须在将数据存储到 Blobstore 之前在服务器上预处理数据),那么您要么必须使用已弃用的Files API,或使用URLFetch API上传数据。这是一个完整的示例应用程序,它将在 Blobstore 中为您存储一个示例文件。package sampleimport ( "bytes" "net/http" "mime/multipart" "appengine" "appengine/blobstore" "appengine/urlfetch")const SampleData = `foo,bar,spam,eggs`func init() { http.HandleFunc("/test", StoreSomeData) http.HandleFunc("/upload", Upload)}func StoreSomeData(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) // First you need to create the upload URL: u, err := blobstore.UploadURL(c, "/upload", nil) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) c.Errorf("%s", err) return } // Now you can prepare a form that you will submit to that URL. var b bytes.Buffer fw := multipart.NewWriter(&b) // Do not change the form field, it must be "file"! // You are free to change the filename though, it will be stored in the BlobInfo. file, err := fw.CreateFormFile("file", "example.csv") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) c.Errorf("%s", err) return } if _, err = file.Write([]byte(SampleData)); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) c.Errorf("%s", err) return } // Don't forget to close the multipart writer. // If you don't close it, your request will be missing the terminating boundary. fw.Close() // Now that you have a form, you can submit it to your handler. req, err := http.NewRequest("POST", u.String(), &b) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) c.Errorf("%s", err) return } // Don't forget to set the content type, this will contain the boundary. req.Header.Set("Content-Type", fw.FormDataContentType()) // Now submit the request. client := urlfetch.Client(c) res, err := client.Do(req) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) c.Errorf("%s", err) return } // Check the response status, it should be whatever you return in the `/upload` handler. if res.StatusCode != http.StatusCreated { http.Error(w, err.Error(), http.StatusInternalServerError) c.Errorf("bad status: %s", res.Status) return } // Everything went fine. w.WriteHeader(res.StatusCode)}func Upload(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) // Here we just checked that the upload went through as expected. if _, _, err := blobstore.ParseUpload(r); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) c.Errorf("%s", err) return } // Everything seems fine. Signal the other handler using the status code. w.WriteHeader(http.StatusCreated)}现在,如果你curl http://localhost:8080/test,它将在 Blobstore 中存储一个文件。重要提示:我不确定您对自己的应用程序发出的请求的带宽费用如何收费。在最坏的情况下,您将被收取内部流量费用,这比正常带宽 iirc 便宜。