使用AJAX将GAE文件上传到blobstore

时间:2015-04-13 15:22:13

标签: javascript ajax google-app-engine file-upload go

我目前正在开发一个用Go for Google App Engine编写的项目。我无法将文件/图像上传到blobstore而无需重新加载网站。

所以这是html表单:

<form id="file-form" action="{{.UploadUrl}}" method="POST" enctype="multipart/form-data">
    <fieldset style="width: 100%;" data-uk-margin>
        <div class="uk-form-row">
            <div id="fields"></div>
        </div>

        <div class="uk-form-row" style="padding-top: 5px; padding-bottom: 5px;">
            <textarea id="textArea" cols="" rows="10" name="description" placeholder="Description"></textarea>
        </div>                      
        <div class="uk-form-row" style="padding-top: 5px; padding-bottom: 5px;">
            <p>Upload File: </p> <input id="file-select" type="file" name="file-select" accept="image/png">
        </div>                              
        <div class="uk-form-row" style="opacity: 1.0;">
            <div class="uk-flex uk-flex-center" id="buttonDiv">
               <button type="submit" id="submitButton" class="uk-button uk-button-primary">Upload</button>
            </div>
        </div>
    </fieldset>
</form>

用于上传图片的javascript代码:

var form = document.getElementById("file-form");
            var fileSelect = document.getElementById("file-select");
            var uploadButton = document.getElementById("submitButton");
            var description = document.getElementById("textArea");

            form.onsubmit = function(event) {
                event.preventDefault();

                uploadButton.innerHTML = "Uploading...";

                if (fileSelect.files.length == 0) {
                    alert("No images selected");
                    uploadButton.innerHTML = "Upload";
                    return;
                }

                var file = fileSelect.files[0];
                console.log(file.name);
                var formData = new FormData();
                formData.append("file", file);
                formData.append("description", description.value);

                var xhr = new XMLHttpRequest();
                xhr.open('POST', "/api/files/fileUpload", true);

                xhr.onload = function() {
                    if (xhr.status === 200) {
                        uploadButton.innerHTML = "Upload"
                    } else {
                        alert("An error occurred!");
                    }
                }
                xhr.send(formData);
            }

Go方法接收文件:

c := appengine.NewContext(r)
    u := user.Current(c)

    if u == nil {
        url, err := user.LoginURL(c, r.URL.String())
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        w.Header().Set("Location", url)
        w.WriteHeader(http.StatusFound)
        return
    }

    logoutUrl, e := user.LogoutURL(c, "/redirect")
    if e != nil {
        panic(e)
    }
    email := u.Email

    uploadURL, error := blobstore.UploadURL(c, "/api/files/fileUpload", nil)
    if error != nil {
        panic(error)
    }

    data := WebpageData{LogoutUrl: logoutUrl, UserName: email, UploadUrl: uploadURL}

    template := template.Must(template.New("template").Parse(fileValue("./console/page/newForm.html")))

    err := template.Execute(w, data)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }

最后是困扰我的错误: 1.从浏览器的js控制台:

Failed to load resource: the server responded with a status of 500 (Internal Server Error)
  1. 来自go console / log:

    2015/04/13 15:10:15 http:恐慌服务127.0.0.1:49543:mime:没有媒体类型 goroutine 16 [正在运行]: 净/ http.func·011()     /private/var/folders/00/0v42r000h01000cxqpysvccm003chb/T/appengine/go_appengine/goroot/src/net/http/server.go:1130 + 0xbb api.check(0xb0db00,0xc20800a970)     api / api.go:40 + 0x50 api.fileUploadHandler(0xb136e0,0xc208045540,0xc2080f1d40)     api / files.go:19 + 0x8a net / http.HandlerFunc.ServeHTTP(0x5a2088,0xb136e0,0xc208045540,0xc2080f1d40)     /private/var/folders/00/0v42r000h01000cxqpysvccm003chb/T/appengine/go_appengine/goroot/src/net/http/server.go:1265 + 0x41 net / http。(* ServeMux).ServeHTTP(0xc20803a690,0xb136e0,0xc208045540,0xc2080f1d40)     /private/var/folders/00/0v42r000h01000cxqpysvccm003chb/T/appengine/go_appengine/goroot/src/net/http/server.go:1541+ 0x17d appengine_internal.handleFilteredHTTP(0xb136e0,0xc208045540,0xc2080f1d40)     /private/var/folders/00/0v42r000h01000cxqpysvccm003chb/T/appengine/go_appengine/goroot/src/appengine_internal/api_dev.go:98+0x413 net / http.HandlerFunc.ServeHTTP(0x5a20f8,0xb136e0,0xc208045540,0xc2080f1d40)     /private/var/folders/00/0v42r000h01000cxqpysvccm003chb/T/appengine/go_appengine/goroot/src/net/http/server.go:1265 + 0x41 net / http.serverHandler.ServeHTTP(0xc208042120,0xb136e0,0xc208045540,0xc2080f1d40)     /private/var/folders/00/0v42r000h01000cxqpysvccm003chb/T/appengine/go_appengine/goroot/src/net/http/server.go:1703 + 0x19a 净/ HTTP(*康恩).serve(0xc2080454a0)     /private/var/folders/00/0v42r000h01000cxqpysvccm003chb/T/appengine/go_appengine/goroot/src/net/http/server.go:1204 + 0xb57 由net / http。(* Server).Serve创建     /private/var/folders/00/0v42r000h01000cxqpysvccm003chb/T/appengine/go_appengine/goroot/src/net/http/server.go:1751 + 0x35e

  2. 任何想法如何解决这个问题。 在此先感谢:)

1 个答案:

答案 0 :(得分:-1)

不推荐使用Blobstore:https://cloud.google.com/appengine/docs/go/blobstore/reference。以下是将文件上传到GCS的方法:

import (
    // these are the appengine imports
    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"
    "google.golang.org/appengine"
    "google.golang.org/appengine/datastore"
    "google.golang.org/appengine/file"
    "google.golang.org/appengine/urlfetch"
    "google.golang.org/cloud"
    "google.golang.org/cloud/storage"
)

func serveFilesUpload(res http.ResponseWriter, req *http.Request) {
    ctx := appengine.NewContext(req)

    // every app engine app comes with a default bucket
    bucket, err := file.DefaultBucketName(ctx)
    if err != nil {
        panic(err)
    }

    // we can't use the regular http client because we need
    // oauth headers added, and also need to use urlfetch
    // for app engine
    hc := &http.Client{
        Transport: &oauth2.Transport{
            Source: google.AppEngineTokenSource(ctx, storage.ScopeFullControl),
            Base:   &urlfetch.Transport{Context: ctx},
        },
    }

    // I'm just giving files random names
    id := uuid.NewRandom().String()

    // this get's the file out of the multipart form
    ff, _, err := req.FormFile("file")
    if err != nil {
        panic(err)
    }
    defer ff.Close()

    cctx := cloud.NewContext(appengine.AppID(ctx), hc)
    wc := storage.NewWriter(cctx, bucket, id)
    io.Copy(wc, ff)
    // normally you'd just defer the .Close, but in this case
    // we care about the error it returns
    err = wc.Close()
    if err != nil {
        panic(err)
    }

    json.NewEncoder(res).Encode(id)
}

此处提供了完整的示例:https://github.com/calebdoxsey/tutorials/tree/master/appengine/cms