...

Source file src/github.com/go-kivik/kivik/v4/pouchdb/attachments.go

Documentation: github.com/go-kivik/kivik/v4/pouchdb

     1  // Licensed under the Apache License, Version 2.0 (the "License"); you may not
     2  // use this file except in compliance with the License. You may obtain a copy of
     3  // the License at
     4  //
     5  //  http://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     9  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    10  // License for the specific language governing permissions and limitations under
    11  // the License.
    12  
    13  //go:build js
    14  
    15  package pouchdb
    16  
    17  import (
    18  	"context"
    19  	"io"
    20  	"strings"
    21  	"sync"
    22  
    23  	"github.com/gopherjs/gopherjs/js"
    24  	"github.com/gopherjs/jsbuiltin"
    25  
    26  	"github.com/go-kivik/kivik/v4/driver"
    27  	"github.com/go-kivik/kivik/v4/pouchdb/bindings"
    28  )
    29  
    30  func (d *db) PutAttachment(ctx context.Context, docID string, att *driver.Attachment, options driver.Options) (newRev string, err error) {
    31  	opts := map[string]interface{}{}
    32  	options.Apply(opts)
    33  	rev, _ := opts["rev"].(string)
    34  	result, err := d.db.PutAttachment(ctx, docID, att.Filename, rev, att.Content, att.ContentType)
    35  	if err != nil {
    36  		return "", err
    37  	}
    38  	return result.Get("rev").String(), nil
    39  }
    40  
    41  func (d *db) GetAttachment(ctx context.Context, docID, filename string, options driver.Options) (*driver.Attachment, error) {
    42  	opts := map[string]interface{}{}
    43  	options.Apply(opts)
    44  	result, err := d.db.GetAttachment(ctx, docID, filename, opts)
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  	return parseAttachment(result)
    49  }
    50  
    51  func parseAttachment(obj *js.Object) (att *driver.Attachment, err error) {
    52  	defer bindings.RecoverError(&err)
    53  	if jsbuiltin.TypeOf(obj.Get("write")) == jsbuiltin.TypeFunction {
    54  		// This looks like a Buffer object; we're in Node.js
    55  		body := obj.Call("toString", "binary").String()
    56  		// It might make sense to wrap the Buffer itself in an io.Reader interface,
    57  		// but since this is only for testing, I'm taking the lazy way out, even
    58  		// though it means slurping an extra copy into memory.
    59  		return &driver.Attachment{
    60  			Content: io.NopCloser(strings.NewReader(body)),
    61  		}, nil
    62  	}
    63  	// We're in the browser
    64  	return &driver.Attachment{
    65  		ContentType: obj.Get("type").String(),
    66  		Content:     &blobReader{Object: obj},
    67  	}, nil
    68  }
    69  
    70  type blobReader struct {
    71  	*js.Object
    72  	offset int
    73  	Size   int `js:"size"`
    74  }
    75  
    76  var _ io.ReadCloser = &blobReader{}
    77  
    78  func (b *blobReader) Read(p []byte) (n int, err error) {
    79  	defer bindings.RecoverError(&err)
    80  	if b.offset >= b.Size {
    81  		return 0, io.EOF
    82  	}
    83  	end := b.offset + len(p) + 1 // end is the first byte not included, not the last byte included, so add 1
    84  	if end > b.Size {
    85  		end = b.Size
    86  	}
    87  	slice := b.Call("slice", b.offset, end)
    88  	fileReader := js.Global.Get("FileReader").New()
    89  	var wg sync.WaitGroup
    90  	wg.Add(1)
    91  	fileReader.Set("onload", js.MakeFunc(func(this *js.Object, _ []*js.Object) interface{} {
    92  		defer wg.Done()
    93  		n = copy(p, js.Global.Get("Uint8Array").New(this.Get("result")).Interface().([]uint8))
    94  		return nil
    95  	}))
    96  	fileReader.Call("readAsArrayBuffer", slice)
    97  	wg.Wait()
    98  	b.offset += n
    99  	return
   100  }
   101  
   102  func (b *blobReader) Close() (err error) {
   103  	defer bindings.RecoverError(&err)
   104  	b.Call("close")
   105  	return nil
   106  }
   107  
   108  func (d *db) DeleteAttachment(ctx context.Context, docID, filename string, options driver.Options) (newRev string, err error) {
   109  	opts := map[string]interface{}{}
   110  	options.Apply(opts)
   111  	rev, _ := opts["rev"].(string)
   112  	result, err := d.db.RemoveAttachment(ctx, docID, filename, rev)
   113  	if err != nil {
   114  		return "", err
   115  	}
   116  	return result.Get("rev").String(), nil
   117  }
   118  

View as plain text