Skip to content

Commit 3496dbe

Browse files
authored
Merge pull request #195 from R-ArcGIS/attachments
Attachments
2 parents 71a25f5 + 8f6023c commit 3496dbe

File tree

2 files changed

+109
-4
lines changed

2 files changed

+109
-4
lines changed

R/attachments.R

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
query_layer_attachments <- function(
4242
x,
4343
definition_expression = "1=1",
44+
attachments_definition_expression = NULL,
4445
object_ids = NULL,
4546
global_ids = NULL,
4647
attachment_types = NULL,
@@ -50,6 +51,11 @@ query_layer_attachments <- function(
5051
# Ignored arguments for now:
5152
# returnMetadata, size,
5253
) {
54+
check_string(definition_expression, allow_null = TRUE)
55+
check_string(attachments_definition_expression, allow_null = TRUE)
56+
check_character(global_ids, allow_null = TRUE)
57+
# TODO validate that object_ids is a vector
58+
5359
# ensure that attachments are available.
5460
if (!x[["hasAttachments"]]) {
5561
cli::cli_abort("{.arg layer} does not support attachments.")
@@ -75,12 +81,21 @@ query_layer_attachments <- function(
7581

7682
req <- httr2::req_body_form(
7783
b_req,
78-
objectIds = object_ids,
79-
globalIds = global_ids,
84+
# TODO test these why aren't these working?!!
85+
objectIds = paste(object_ids, collapse = ","),
86+
# TODO create a test for this
87+
globalIds = paste(global_ids, collapse = ","),
8088
attachmentTypes = attachment_types,
89+
# TODO document common examples:
90+
# filter based on
91+
# - date
92+
# - common prefix
93+
# - numeric value
8194
definitionExpression = definition_expression,
95+
attachmentsDefinitionExpression = attachments_definition_expression,
8296
keywords = keywords,
8397
returnUrl = TRUE,
98+
returnMetadata = TRUE,
8499
f = "json"
85100
)
86101

@@ -96,6 +111,11 @@ query_layer_attachments <- function(
96111
#' @param x the attachmentGroups column from the query results
97112
#' @noRd
98113
unnest_attachment_groups <- function(x) {
114+
if (is.null(x[["attachmentInfos"]])) {
115+
cli::cli_alert_info("No attachments found.")
116+
return(NULL)
117+
}
118+
99119
n_elem <- vapply(x[["attachmentInfos"]], nrow, integer(1))
100120
res <- cbind(
101121
x[rep.int(1:nrow(x), n_elem), c("parentGlobalId", "parentObjectId")],
@@ -128,6 +148,7 @@ download_attachments <- function(
128148
attachments,
129149
out_dir,
130150
...,
151+
overwrite = FALSE,
131152
.progress = TRUE,
132153
token = arc_token()) {
133154
# check that the input is a data frame with the appropriate types
@@ -195,9 +216,32 @@ download_attachments <- function(
195216

196217
# create the output path names
197218
out_fps <- file.path(out_dir, attachments[["name"]])
219+
already_exist <- file.exists(out_fps)
220+
221+
# required fields
222+
urls <- attachments[["url"]]
223+
content_types <- attachments[["contentType"]]
224+
225+
if (!overwrite && any(already_exist)) {
226+
# Files with the same name found.
227+
cli::cli_inform(
228+
c(
229+
"Files with the same name found in {.path {out_dir}}",
230+
"i" = "Existing files: {.file {out_fps[already_exist]}}",
231+
">" = "set {.arg overwrite = TRUE} to overwrite these files"
232+
)
233+
)
234+
# subset to the files that dont already exist
235+
out_fps <- out_fps[!already_exist]
236+
urls <- urls[!already_exist]
237+
content_types <- content_types[!already_exist]
238+
}
239+
# TODO check if files exist, if they do provide a message
240+
# saying we're skipping downloading.
241+
# To download use `overwrite = TRUE`
198242

199243
# create the requests
200-
attachment_reqs <- lapply(attachments[["url"]], arc_base_req, token = token)
244+
attachment_reqs <- lapply(urls, arc_base_req, token = token)
201245

202246
# perform the requests
203247
resps <- httr2::req_perform_parallel(
@@ -207,7 +251,7 @@ download_attachments <- function(
207251
)
208252

209253

210-
Map(.download_attachment, resps, attachments[["contentType"]], out_fps)
254+
Map(.download_attachment, resps, content_types, out_fps)
211255
}
212256

213257
.download_attachment <- function(.resp, .content_type, .fp) {

dev/attachments-demo.R

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# install the development version
2+
# install.packages("pak")
3+
# pak::pak("r-arcgis/arcgislayers")
4+
5+
# for authorizing to your portal
6+
library(arcgisutils)
7+
8+
# for accessing feature service content
9+
library(arcgislayers)
10+
11+
# authorize
12+
set_arc_token(auth_user())
13+
14+
# URL to the Survey123 feature service with attachments
15+
furl <- "https://services1.arcgis.com/hLJbHVT9ZrDIzK0I/arcgis/rest/services/v8_Wide_Area_Search_Form_Feature_Layer___a2fe9c/FeatureServer/0"
16+
17+
# create a reference to it in R
18+
layer <- arc_open(furl)
19+
20+
# There are two parts to working with attachments:
21+
# 1. Finding the attachments associated with a feature service
22+
# 2. After finding the attachments, we can download them to our machine
23+
24+
# Query the attachments of a layer using query_layer_attachments()
25+
# By default this returns metadata about every attachment in your
26+
# feature service
27+
att <- query_layer_attachments(layer)
28+
att
29+
30+
# We can limit this by providing a SQL where clause to the
31+
# definition_expression argument.
32+
# For example to find all of the attachments that have the
33+
# followup_status field set to `needs_followup` we can provide the
34+
# following definition_expression
35+
query_layer_attachments(
36+
layer, "followup_status = 'needs_followup'"
37+
)
38+
39+
# To find all of the attachments from after a point in time
40+
query_layer_attachments(
41+
layer, "start_time >= '2023-01-01'"
42+
)
43+
44+
# To find attachments with a name that starts with `image0`
45+
query_layer_attachments(
46+
layer,
47+
attachments_definition_expression = "att_name like 'image0%'"
48+
)
49+
50+
# Find attachments that contain "20221005"
51+
query_layer_attachments(
52+
layer,
53+
attachments_definition_expression = "att_name like '%20221005%'"
54+
)
55+
56+
57+
# to download the attachments:
58+
# res <- download_attachments(
59+
# att,
60+
# "dev/field_images"
61+
# )

0 commit comments

Comments
 (0)