Skip to contents

Implements Zotero's full upload protocol: create the attachment item, request upload authorization (an identical file already in storage short-circuits as exists), upload to the returned storage URL, register the upload, and verify the attachment's MD5 server-side. Uploads may consume Zotero storage quota and have immediate external effects.

Usage

ztAttach(
  config,
  parentKey,
  filePath,
  library = "user",
  filename = basename(filePath),
  contentType = .zotContentType(filePath),
  fileTransport = .zotFileTransport()
)

Arguments

config

A zotConfig() object.

parentKey

Key of the regular item receiving the file, or NA for a standalone attachment.

filePath

Local file to upload.

library

"user" or a group id.

filename

Stored filename; defaults to the file's basename.

contentType

MIME type; defaults by extension for pdf/epub, else application/octet-stream.

fileTransport

The three protocol steps as an injectable list (authorize, upload, register); the default performs them for real. Tests replace it.

Value

A list: status ("uploaded", "exists" or "failed"), the attachment key, and error when failed.

Details

The default file transport performs every external protocol step. Supplying fileTransport replaces only authorization, byte upload, and registration; attachment creation and final API verification still use config. A stored file with the same MD5 returns "exists" before uploading bytes.

Examples

Path <- tempfile(fileext = ".pdf")
writeBin(as.raw(1:8), Path)
Performer <- function(config, method, path, query, body, version) {
  list(
    status = 200L, headers = list(),
    body = list(successful = list(`0` = list(key = "ATT1")))
  )
}
Config <- structure(
  list(userID = "42", key = "example", apiBase = "https://example.invalid",
       performer = Performer),
  class = "zotConfig"
)
Transport <- list(
  authorize = function(...) list(exists = 1L),
  upload = function(...) stop("upload should not run"),
  register = function(...) stop("registration should not run")
)
ztAttach(Config, parentKey = NA_character_, filePath = Path,
         fileTransport = Transport)
#> $status
#> [1] "exists"
#> 
#> $key
#> [1] "ATT1"
#> 
unlink(Path)