mirror of
https://github.com/actix/examples
synced 2024-11-27 16:02:57 +01:00
migrate s3 example to aws-sdk-s3
This commit is contained in:
parent
0149e64c7a
commit
4840cfdb68
565
Cargo.lock
generated
565
Cargo.lock
generated
@ -450,7 +450,7 @@ dependencies = [
|
||||
"openssl",
|
||||
"pin-project-lite 0.2.9",
|
||||
"tokio-openssl",
|
||||
"tokio-rustls",
|
||||
"tokio-rustls 0.23.4",
|
||||
"tokio-util 0.7.3",
|
||||
"webpki-roots 0.22.4",
|
||||
]
|
||||
@ -569,7 +569,7 @@ dependencies = [
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"generic-array 0.14.5",
|
||||
"hmac 0.12.1",
|
||||
"hmac",
|
||||
"http",
|
||||
"local-channel",
|
||||
"mime",
|
||||
@ -1080,6 +1080,306 @@ dependencies = [
|
||||
"webpki-roots 0.22.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-config"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11a8c971b0cb0484fc9436a291a44503b95141edc36ce7a6af6b6d7a06a02ab0"
|
||||
dependencies = [
|
||||
"aws-http",
|
||||
"aws-sdk-sso",
|
||||
"aws-sdk-sts",
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-client",
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-http-tower",
|
||||
"aws-smithy-json",
|
||||
"aws-smithy-types",
|
||||
"aws-types",
|
||||
"bytes 1.2.0",
|
||||
"hex",
|
||||
"http",
|
||||
"hyper 0.14.20",
|
||||
"ring",
|
||||
"tokio 1.20.0",
|
||||
"tower",
|
||||
"tracing",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-endpoint"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bc956f415dda77215372e5bc751a2463d1f9a1ec34edf3edc6c0ff67e5c8e43"
|
||||
dependencies = [
|
||||
"aws-smithy-http",
|
||||
"aws-types",
|
||||
"http",
|
||||
"regex",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-http"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a0d98a1d606aa24554e604f220878db4aa3b525b72f88798524497cc3867fc6"
|
||||
dependencies = [
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-types",
|
||||
"aws-types",
|
||||
"bytes 1.2.0",
|
||||
"http",
|
||||
"http-body 0.4.5",
|
||||
"lazy_static",
|
||||
"percent-encoding",
|
||||
"pin-project-lite 0.2.9",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-sdk-s3"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f6e22f5641db610235c0c5fb768b5925a6317b16b12e4ab5a625cfed176f8a2"
|
||||
dependencies = [
|
||||
"aws-endpoint",
|
||||
"aws-http",
|
||||
"aws-sig-auth",
|
||||
"aws-sigv4",
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-client",
|
||||
"aws-smithy-eventstream",
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-http-tower",
|
||||
"aws-smithy-types",
|
||||
"aws-smithy-xml",
|
||||
"aws-types",
|
||||
"bytes 1.2.0",
|
||||
"http",
|
||||
"md-5",
|
||||
"tokio-stream",
|
||||
"tower",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-sdk-sso"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baa0c66fab12976065403cf4cafacffe76afa91d0da335d195af379d4223d235"
|
||||
dependencies = [
|
||||
"aws-endpoint",
|
||||
"aws-http",
|
||||
"aws-sig-auth",
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-client",
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-http-tower",
|
||||
"aws-smithy-json",
|
||||
"aws-smithy-types",
|
||||
"aws-types",
|
||||
"bytes 1.2.0",
|
||||
"http",
|
||||
"tokio-stream",
|
||||
"tower",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-sdk-sts"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "048037cdfd7f42fb29b5f969c7f639b4b7eac00e8f911e4eac4f89fb7b3a0500"
|
||||
dependencies = [
|
||||
"aws-endpoint",
|
||||
"aws-http",
|
||||
"aws-sig-auth",
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-client",
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-http-tower",
|
||||
"aws-smithy-query",
|
||||
"aws-smithy-types",
|
||||
"aws-smithy-xml",
|
||||
"aws-types",
|
||||
"bytes 1.2.0",
|
||||
"http",
|
||||
"tower",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-sig-auth"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8386fc0d218dbf2011f65bd8300d21ba98603fd150b962f61239be8b02d1fc6"
|
||||
dependencies = [
|
||||
"aws-sigv4",
|
||||
"aws-smithy-eventstream",
|
||||
"aws-smithy-http",
|
||||
"aws-types",
|
||||
"http",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-sigv4"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd866926c2c4978210bcb01d7d1b431c794f0c23ca9ee1e420204b018836b5fb"
|
||||
dependencies = [
|
||||
"aws-smithy-eventstream",
|
||||
"aws-smithy-http",
|
||||
"bytes 1.2.0",
|
||||
"form_urlencoded",
|
||||
"hex",
|
||||
"http",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"regex",
|
||||
"ring",
|
||||
"time 0.3.11",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-async"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "deb59cfdd21143006c01b9ca4dc4a9190b8c50c2ef831f9eb36f54f69efa42f1"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"pin-project-lite 0.2.9",
|
||||
"tokio 1.20.0",
|
||||
"tokio-stream",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-client"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44243329ba8618474c3b7f396de281f175ae172dd515b3d35648671a3cf51871"
|
||||
dependencies = [
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-http-tower",
|
||||
"aws-smithy-types",
|
||||
"bytes 1.2.0",
|
||||
"fastrand",
|
||||
"http",
|
||||
"http-body 0.4.5",
|
||||
"hyper 0.14.20",
|
||||
"hyper-rustls",
|
||||
"lazy_static",
|
||||
"pin-project-lite 0.2.9",
|
||||
"tokio 1.20.0",
|
||||
"tower",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-eventstream"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e69ee49b9ed0ef080a6e18c08644521d3026029eb65dfc8c694315e1ae3118bc"
|
||||
dependencies = [
|
||||
"aws-smithy-types",
|
||||
"bytes 1.2.0",
|
||||
"crc32fast",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-http"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fba78f69a5bbe7ac1826389304c67b789032d813574e78f9a2d450634277f833"
|
||||
dependencies = [
|
||||
"aws-smithy-eventstream",
|
||||
"aws-smithy-types",
|
||||
"bytes 1.2.0",
|
||||
"bytes-utils",
|
||||
"futures-core",
|
||||
"http",
|
||||
"http-body 0.4.5",
|
||||
"hyper 0.14.20",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"pin-project-lite 0.2.9",
|
||||
"tokio 1.20.0",
|
||||
"tokio-util 0.7.3",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-http-tower"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff8a512d68350561e901626baa08af9491cfbd54596201b84b4da846a59e4da3"
|
||||
dependencies = [
|
||||
"aws-smithy-http",
|
||||
"bytes 1.2.0",
|
||||
"http",
|
||||
"http-body 0.4.5",
|
||||
"pin-project-lite 0.2.9",
|
||||
"tower",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-json"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31b7633698853aae80bd8b26866531420138eca91ea4620735d20b0537c93c2e"
|
||||
dependencies = [
|
||||
"aws-smithy-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-query"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95a94b5a8cc94a85ccbff89eb7bc80dc135ede02847a73d68c04ac2a3e4cf6b7"
|
||||
dependencies = [
|
||||
"aws-smithy-types",
|
||||
"urlencoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-types"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d230d281653de22fb0e9c7c74d18d724a39d7148e2165b1e760060064c4967c0"
|
||||
dependencies = [
|
||||
"itoa 1.0.2",
|
||||
"num-integer",
|
||||
"ryu",
|
||||
"time 0.3.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-xml"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4aacaf6c0fa549ebe5d9daa96233b8635965721367ee7c69effc8d8078842df3"
|
||||
dependencies = [
|
||||
"xmlparser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-types"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb54f097516352475a0159c9355f8b4737c54044538a4d9aca4d376ef2361ccc"
|
||||
dependencies = [
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-client",
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-types",
|
||||
"http",
|
||||
"rustc_version 0.4.0",
|
||||
"tracing",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backoff"
|
||||
version = "0.2.1"
|
||||
@ -1345,6 +1645,16 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytes-utils"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1934a3ef9cac8efde4966a92781e77713e1ba329f1d42e446c7d7eba340d8ef1"
|
||||
dependencies = [
|
||||
"bytes 1.2.0",
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytestring"
|
||||
version = "1.1.0"
|
||||
@ -1636,7 +1946,7 @@ dependencies = [
|
||||
"aes-gcm",
|
||||
"base64",
|
||||
"hkdf",
|
||||
"hmac 0.12.1",
|
||||
"hmac",
|
||||
"percent-encoding",
|
||||
"rand 0.8.5",
|
||||
"sha2 0.10.2",
|
||||
@ -1770,16 +2080,6 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-mac"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714"
|
||||
dependencies = [
|
||||
"generic-array 0.14.5",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "csv"
|
||||
version = "1.1.6"
|
||||
@ -1802,6 +2102,15 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ct-logs"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1a816186fa68d9e426e3cb4ae4dff1fcd8e4a2c34b781bf7a822574a0d0aac8"
|
||||
dependencies = [
|
||||
"sct 0.6.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctr"
|
||||
version = "0.8.0"
|
||||
@ -1984,27 +2293,6 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-next"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys-next"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "discard"
|
||||
version = "1.0.4"
|
||||
@ -2748,17 +3036,7 @@ version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
|
||||
dependencies = [
|
||||
"hmac 0.12.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
|
||||
dependencies = [
|
||||
"crypto-mac",
|
||||
"digest 0.9.0",
|
||||
"hmac",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2918,6 +3196,23 @@ dependencies = [
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64"
|
||||
dependencies = [
|
||||
"ct-logs",
|
||||
"futures-util",
|
||||
"hyper 0.14.20",
|
||||
"log",
|
||||
"rustls 0.19.1",
|
||||
"rustls-native-certs",
|
||||
"tokio 1.20.0",
|
||||
"tokio-rustls 0.22.0",
|
||||
"webpki 0.21.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-tls"
|
||||
version = "0.4.3"
|
||||
@ -3455,17 +3750,6 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
|
||||
|
||||
[[package]]
|
||||
name = "md-5"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15"
|
||||
dependencies = [
|
||||
"block-buffer 0.9.0",
|
||||
"digest 0.9.0",
|
||||
"opaque-debug 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "md-5"
|
||||
version = "0.10.1"
|
||||
@ -3622,9 +3906,9 @@ dependencies = [
|
||||
"futures-executor",
|
||||
"futures-util",
|
||||
"hex",
|
||||
"hmac 0.12.1",
|
||||
"hmac",
|
||||
"lazy_static",
|
||||
"md-5 0.10.1",
|
||||
"md-5",
|
||||
"os_info",
|
||||
"pbkdf2",
|
||||
"percent-encoding",
|
||||
@ -3643,7 +3927,7 @@ dependencies = [
|
||||
"take_mut",
|
||||
"thiserror",
|
||||
"tokio 1.20.0",
|
||||
"tokio-rustls",
|
||||
"tokio-rustls 0.23.4",
|
||||
"tokio-util 0.7.3",
|
||||
"trust-dns-proto",
|
||||
"trust-dns-resolver",
|
||||
@ -3682,17 +3966,18 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "multipart-s3"
|
||||
name = "multipart-s3-example"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"actix-multipart",
|
||||
"actix-web",
|
||||
"actix-web-lab",
|
||||
"aws-config",
|
||||
"aws-sdk-s3",
|
||||
"dotenv",
|
||||
"env_logger 0.9.0",
|
||||
"futures-util",
|
||||
"log",
|
||||
"rusoto_core",
|
||||
"rusoto_s3",
|
||||
"sanitize-filename",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -4307,8 +4592,8 @@ dependencies = [
|
||||
"byteorder",
|
||||
"bytes 1.2.0",
|
||||
"fallible-iterator",
|
||||
"hmac 0.12.1",
|
||||
"md-5 0.10.1",
|
||||
"hmac",
|
||||
"md-5",
|
||||
"memchr",
|
||||
"rand 0.8.5",
|
||||
"sha2 0.10.2",
|
||||
@ -4698,17 +4983,6 @@ dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
|
||||
dependencies = [
|
||||
"getrandom 0.2.7",
|
||||
"redox_syscall",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.6.0"
|
||||
@ -4902,88 +5176,6 @@ dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusoto_core"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1db30db44ea73551326269adcf7a2169428a054f14faf9e1768f2163494f2fa2"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64",
|
||||
"bytes 1.2.0",
|
||||
"crc32fast",
|
||||
"futures",
|
||||
"http",
|
||||
"hyper 0.14.20",
|
||||
"hyper-tls 0.5.0",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"rusoto_credential",
|
||||
"rusoto_signature",
|
||||
"rustc_version 0.4.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio 1.20.0",
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusoto_credential"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee0a6c13db5aad6047b6a44ef023dbbc21a056b6dab5be3b79ce4283d5c02d05"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
"dirs-next",
|
||||
"futures",
|
||||
"hyper 0.14.20",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"shlex",
|
||||
"tokio 1.20.0",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusoto_s3"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7aae4677183411f6b0b412d66194ef5403293917d66e70ab118f07cc24c5b14d"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes 1.2.0",
|
||||
"futures",
|
||||
"rusoto_core",
|
||||
"xml-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusoto_signature"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5ae95491c8b4847931e291b151127eccd6ff8ca13f33603eb3d0035ecb05272"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bytes 1.2.0",
|
||||
"chrono",
|
||||
"digest 0.9.0",
|
||||
"futures",
|
||||
"hex",
|
||||
"hmac 0.11.0",
|
||||
"http",
|
||||
"hyper 0.14.20",
|
||||
"log",
|
||||
"md-5 0.9.1",
|
||||
"percent-encoding",
|
||||
"pin-project-lite 0.2.9",
|
||||
"rusoto_credential",
|
||||
"rustc_version 0.4.0",
|
||||
"serde",
|
||||
"sha2 0.9.9",
|
||||
"tokio 1.20.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusqlite"
|
||||
version = "0.27.0"
|
||||
@ -5116,6 +5308,18 @@ dependencies = [
|
||||
"rustls-pemfile 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-native-certs"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a07b7c1885bd8ed3831c289b7870b13ef46fe0e856d288c30d9cc17d75a2092"
|
||||
dependencies = [
|
||||
"openssl-probe",
|
||||
"rustls 0.19.1",
|
||||
"schannel",
|
||||
"security-framework",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pemfile"
|
||||
version = "0.3.0"
|
||||
@ -5737,7 +5941,7 @@ checksum = "874e93a365a598dc3dadb197565952cb143ae4aa716f7bcc933a8d836f6bf89f"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"tokio 1.20.0",
|
||||
"tokio-rustls",
|
||||
"tokio-rustls 0.23.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -6316,6 +6520,17 @@ dependencies = [
|
||||
"tokio-util 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6"
|
||||
dependencies = [
|
||||
"rustls 0.19.1",
|
||||
"tokio 1.20.0",
|
||||
"webpki 0.21.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.23.4"
|
||||
@ -6399,6 +6614,28 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"pin-project",
|
||||
"pin-project-lite 0.2.9",
|
||||
"tokio 1.20.0",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-layer"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62"
|
||||
|
||||
[[package]]
|
||||
name = "tower-service"
|
||||
version = "0.3.2"
|
||||
@ -6772,6 +7009,12 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urlencoding"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68b90931029ab9b034b300b797048cf23723400aa757e8a2bfb9d748102f9821"
|
||||
|
||||
[[package]]
|
||||
name = "utf-8"
|
||||
version = "0.7.6"
|
||||
@ -7307,10 +7550,10 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xml-rs"
|
||||
version = "0.8.4"
|
||||
name = "xmlparser"
|
||||
version = "0.13.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3"
|
||||
checksum = "114ba2b24d2167ef6d67d7d04c8cc86522b87f490025f39f0303b7db5bf5e3d8"
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
|
@ -1,4 +1,4 @@
|
||||
AWS_REGION=
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_S3_BUCKET_NAME=
|
||||
AWS_REGION=
|
||||
|
@ -1,18 +1,20 @@
|
||||
[package]
|
||||
name = "multipart-s3"
|
||||
name = "multipart-s3-example"
|
||||
version = "1.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
actix-web = "4"
|
||||
actix-multipart = "0.4"
|
||||
actix-web = "4"
|
||||
actix-web-lab = "0.16"
|
||||
|
||||
dotenv = "0.15.0"
|
||||
aws-config = "0.46"
|
||||
aws-sdk-s3 = "0.16"
|
||||
|
||||
dotenv = "0.15"
|
||||
env_logger = "0.9"
|
||||
futures-util = { version = "0.3.17", default-features = false, features = ["std"] }
|
||||
log = "0.4"
|
||||
rusoto_core = "0.48"
|
||||
rusoto_s3 = "0.48"
|
||||
sanitize-filename = "0.4"
|
||||
serde = { version = "1.0.104", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
|
@ -1,30 +1,21 @@
|
||||
# Multipart + AWS S3
|
||||
|
||||
Upload a file in multipart form to aws s3 (https://github.com/rusoto/rusoto).
|
||||
Upload a file in multipart form to AWS S3 using [AWS S3 SDK](https://crates.io/crates/aws-sdk-s3).
|
||||
Receive multiple data in multipart form in JSON format and receive it as a struct.
|
||||
|
||||
# Usage
|
||||
|
||||
```
|
||||
```sh
|
||||
cd forms/multipart-s3
|
||||
```
|
||||
|
||||
1. copy .env.example .env
|
||||
1. edit .env AWS_ACCESS_KEY_ID=you_key
|
||||
1. edit .env AWS_SECRET_ACCESS_KEY=you_key
|
||||
1. edit .env AWS_S3_BUCKET_NAME=you_key
|
||||
1. edit .env AWS_ACCESS_KEY_ID=your_key
|
||||
1. edit .env AWS_SECRET_ACCESS_KEY=your_key
|
||||
1. edit .env AWS_S3_BUCKET_NAME=your_chosen_region
|
||||
|
||||
# Running Server
|
||||
|
||||
```
|
||||
cd forms/multipart-s3
|
||||
cargo run (or ``cargo watch -x run``)
|
||||
```sh
|
||||
cargo run
|
||||
```
|
||||
|
||||
http://localhost:8080
|
||||
|
||||
# Using Other Regions
|
||||
|
||||
<!-- - https://www.rusoto.org/regions.html -->
|
||||
|
||||
- https://docs.rs/rusoto_core/0.42.0/rusoto_core/enum.Region.html
|
||||
<http://localhost:8080>
|
||||
|
35
forms/multipart-s3/src/index.html
Normal file
35
forms/multipart-s3/src/index.html
Normal file
@ -0,0 +1,35 @@
|
||||
<html>
|
||||
<head><title>Upload Test</title></head>
|
||||
<body>
|
||||
<form target="/" method="post" enctype="multipart/form-data" id="myForm" >
|
||||
<input type="text" id="text" name="text" value="test_text"/>
|
||||
<input type="number" id="number" name="number" value="123123"/>
|
||||
<input type="button" value="Submit" onclick="myFunction()"></button>
|
||||
</form>
|
||||
<input type="file" multiple name="file" id="myFile"/>
|
||||
</body>
|
||||
<script>
|
||||
|
||||
function myFunction(){
|
||||
var myForm = document.getElementById('myForm');
|
||||
var myFile = document.getElementById('myFile');
|
||||
|
||||
let formData = new FormData();
|
||||
const obj = {
|
||||
text: document.getElementById('text').value,
|
||||
number: Number(document.getElementById('number').value)
|
||||
};
|
||||
const json = JSON.stringify(obj);
|
||||
console.log(obj);
|
||||
console.log(json);
|
||||
|
||||
formData.append("data", json);
|
||||
formData.append("myFile", myFile.files[0]);
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
request.open("POST", "");
|
||||
request.send(formData);
|
||||
}
|
||||
|
||||
</script>
|
||||
</html>
|
@ -1,12 +1,18 @@
|
||||
use std::{borrow::BorrowMut, env};
|
||||
use std::fs;
|
||||
|
||||
use actix_multipart::Multipart;
|
||||
use actix_web::{middleware::Logger, web, App, Error, HttpResponse, HttpServer};
|
||||
use actix_web::{middleware::Logger, web, App, Error, HttpResponse, HttpServer, Responder};
|
||||
use actix_web_lab::respond::Html;
|
||||
use aws_config::meta::region::RegionProviderChain;
|
||||
use dotenv::dotenv;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
mod utils;
|
||||
use self::utils::upload::{save_file as upload_save_file, split_payload, UploadFile};
|
||||
|
||||
use self::utils::{
|
||||
s3::Client,
|
||||
upload::{save_file as upload_save_file, split_payload, UploadFile},
|
||||
};
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct InpAdd {
|
||||
@ -14,60 +20,31 @@ pub struct InpAdd {
|
||||
pub number: i32,
|
||||
}
|
||||
|
||||
async fn save_file(mut payload: Multipart) -> Result<HttpResponse, Error> {
|
||||
let pl = split_payload(payload.borrow_mut()).await;
|
||||
async fn save_file(
|
||||
s3_client: web::Data<Client>,
|
||||
mut payload: Multipart,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
let pl = split_payload(&mut payload).await;
|
||||
println!("bytes={:#?}", pl.0);
|
||||
|
||||
let inp_info: InpAdd = serde_json::from_slice(&pl.0).unwrap();
|
||||
println!("converter_struct={:#?}", inp_info);
|
||||
println!("tmpfiles={:#?}", pl.1);
|
||||
//make key
|
||||
|
||||
// make key
|
||||
let s3_upload_key = format!("projects/{}/", "posts_id");
|
||||
//create tmp file and upload s3 and remove tmp file
|
||||
let upload_files: Vec<UploadFile> = upload_save_file(pl.1, s3_upload_key).await.unwrap();
|
||||
|
||||
// create tmp file and upload s3 and remove tmp file
|
||||
let upload_files: Vec<UploadFile> = upload_save_file(&s3_client, pl.1, &s3_upload_key)
|
||||
.await
|
||||
.unwrap();
|
||||
println!("upload_files={:#?}", upload_files);
|
||||
|
||||
Ok(HttpResponse::Ok().into())
|
||||
}
|
||||
|
||||
async fn index() -> HttpResponse {
|
||||
let html = r#"<html>
|
||||
<head><title>Upload Test</title></head>
|
||||
<body>
|
||||
<form target="/" method="post" enctype="multipart/form-data" id="myForm" >
|
||||
<input type="text" id="text" name="text" value="test_text"/>
|
||||
<input type="number" id="number" name="number" value="123123"/>
|
||||
<input type="button" value="Submit" onclick="myFunction()"></button>
|
||||
</form>
|
||||
<input type="file" multiple name="file" id="myFile"/>
|
||||
</body>
|
||||
<script>
|
||||
|
||||
function myFunction(){
|
||||
var myForm = document.getElementById('myForm');
|
||||
var myFile = document.getElementById('myFile');
|
||||
|
||||
let formData = new FormData();
|
||||
const obj = {
|
||||
text: document.getElementById('text').value,
|
||||
number: Number(document.getElementById('number').value)
|
||||
};
|
||||
const json = JSON.stringify(obj);
|
||||
console.log(obj);
|
||||
console.log(json);
|
||||
|
||||
formData.append("data", json);
|
||||
formData.append("myFile", myFile.files[0]);
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
request.open("POST", "");
|
||||
request.send(formData);
|
||||
}
|
||||
|
||||
</script>
|
||||
</html>"#;
|
||||
|
||||
HttpResponse::Ok()
|
||||
.content_type("text/html; charset=utf-8")
|
||||
.body(html)
|
||||
async fn index() -> impl Responder {
|
||||
Html(include_str!("./index.html").to_owned())
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
@ -75,21 +52,20 @@ async fn main() -> std::io::Result<()> {
|
||||
dotenv().ok();
|
||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||
|
||||
let aws_access_key_id = env::var("AWS_ACCESS_KEY_ID").expect("AWS_ACCESS_KEY_ID must be set");
|
||||
let aws_secret_access_key =
|
||||
env::var("AWS_SECRET_ACCESS_KEY").expect("AWS_SECRET_ACCESS_KEY must be set");
|
||||
let aws_s3_bucket_name =
|
||||
env::var("AWS_S3_BUCKET_NAME").expect("AWS_S3_BUCKET_NAME must be set");
|
||||
log::info!("creating temporary upload directory");
|
||||
|
||||
log::info!("aws_access_key_id: {aws_access_key_id}");
|
||||
log::info!("aws_secret_access_key: {aws_secret_access_key}");
|
||||
log::info!("aws_s3_bucket_name: {aws_s3_bucket_name}");
|
||||
fs::create_dir_all("./tmp").unwrap();
|
||||
|
||||
std::fs::create_dir_all("./tmp").unwrap();
|
||||
log::info!("configuring S3 client");
|
||||
let aws_region = RegionProviderChain::default_provider().or_else("us-east-1");
|
||||
let aws_config = aws_config::from_env().region(aws_region).load().await;
|
||||
let s3_client = Client::new(&aws_config);
|
||||
|
||||
log::info!("using AWS region: {}", aws_config.region().unwrap());
|
||||
|
||||
log::info!("starting HTTP server at http://localhost:8080");
|
||||
|
||||
HttpServer::new(|| {
|
||||
HttpServer::new(move || {
|
||||
App::new()
|
||||
.service(
|
||||
web::resource("/")
|
||||
@ -97,7 +73,9 @@ async fn main() -> std::io::Result<()> {
|
||||
.route(web::post().to(save_file)),
|
||||
)
|
||||
.wrap(Logger::default())
|
||||
.app_data(web::Data::new(s3_client.clone()))
|
||||
})
|
||||
.workers(2)
|
||||
.bind(("127.0.0.1", 8080))?
|
||||
.run()
|
||||
.await
|
||||
|
@ -1,64 +1,57 @@
|
||||
use std::io::Read as _;
|
||||
use std::{env, fs, io::Read as _};
|
||||
|
||||
use rusoto_core::Region;
|
||||
use rusoto_s3::{DeleteObjectRequest, PutObjectRequest, S3Client, S3};
|
||||
use aws_config::SdkConfig as AwsConfig;
|
||||
use aws_sdk_s3::{types::ByteStream, Client as S3Client};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Client {
|
||||
#[allow(dead_code)]
|
||||
region: Region,
|
||||
s3: S3Client,
|
||||
bucket_name: String,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
// construct S3 testing client
|
||||
pub fn new() -> Client {
|
||||
let region = Region::default();
|
||||
|
||||
pub fn new(config: &AwsConfig) -> Client {
|
||||
Client {
|
||||
region: region.to_owned(),
|
||||
s3: S3Client::new(region),
|
||||
bucket_name: std::env::var("AWS_S3_BUCKET_NAME").unwrap(),
|
||||
s3: S3Client::new(config),
|
||||
bucket_name: env::var("AWS_S3_BUCKET_NAME").unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn url(&self, key: &str) -> String {
|
||||
format!(
|
||||
"https://{}.s3.{}.amazonaws.com/{key}",
|
||||
std::env::var("AWS_S3_BUCKET_NAME").unwrap(),
|
||||
std::env::var("AWS_REGION").unwrap(),
|
||||
env::var("AWS_S3_BUCKET_NAME").unwrap(),
|
||||
env::var("AWS_REGION").unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn put_object(&self, localfilepath: &str, key: &str) -> String {
|
||||
let mut file = std::fs::File::open(localfilepath).unwrap();
|
||||
let mut contents: Vec<u8> = Vec::new();
|
||||
let _ = file.read_to_end(&mut contents);
|
||||
let put_request = PutObjectRequest {
|
||||
bucket: self.bucket_name.to_owned(),
|
||||
key: key.to_owned(),
|
||||
body: Some(contents.into()),
|
||||
..Default::default()
|
||||
};
|
||||
pub async fn put_object(&self, local_path: &str, key: &str) -> String {
|
||||
let mut file = fs::File::open(local_path).unwrap();
|
||||
|
||||
let mut contents =
|
||||
Vec::with_capacity(file.metadata().map(|md| md.len()).unwrap_or(1024) as usize);
|
||||
file.read_to_end(&mut contents).unwrap();
|
||||
|
||||
let _res = self
|
||||
.s3
|
||||
.put_object(put_request)
|
||||
.put_object()
|
||||
.bucket(&self.bucket_name)
|
||||
.key(key)
|
||||
.body(ByteStream::from(contents))
|
||||
.send()
|
||||
.await
|
||||
.expect("Failed to put test object");
|
||||
|
||||
self.url(key)
|
||||
}
|
||||
|
||||
pub async fn delete_object(&self, key: String) {
|
||||
let delete_object_req = DeleteObjectRequest {
|
||||
bucket: self.bucket_name.to_owned(),
|
||||
key: key.to_owned(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let _res = self
|
||||
.s3
|
||||
.delete_object(delete_object_req)
|
||||
pub async fn delete_object(&self, key: &str) {
|
||||
self.s3
|
||||
.delete_object()
|
||||
.bucket(&self.bucket_name)
|
||||
.key(key)
|
||||
.send()
|
||||
.await
|
||||
.expect("Couldn't delete object");
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::{convert::From, io::Write};
|
||||
use std::{convert::From, fs, io::Write};
|
||||
|
||||
use actix_multipart::{Field, Multipart};
|
||||
use actix_web::{web, web::Bytes, Error};
|
||||
@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::utils::s3::Client;
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct UploadFile {
|
||||
pub filename: String,
|
||||
pub key: String,
|
||||
@ -36,6 +36,7 @@ pub struct Tmpfile {
|
||||
pub s3_key: String,
|
||||
pub s3_url: String,
|
||||
}
|
||||
|
||||
impl Tmpfile {
|
||||
fn new(filename: &str) -> Tmpfile {
|
||||
Tmpfile {
|
||||
@ -46,25 +47,25 @@ impl Tmpfile {
|
||||
}
|
||||
}
|
||||
|
||||
async fn s3_upload_and_tmp_remove(&mut self, s3_upload_key: String) {
|
||||
self.s3_upload(s3_upload_key).await;
|
||||
async fn s3_upload_and_tmp_remove(&mut self, client: &Client, s3_upload_key: &str) {
|
||||
self.s3_upload(client, s3_upload_key).await;
|
||||
self.tmp_remove();
|
||||
}
|
||||
|
||||
async fn s3_upload(&mut self, s3_upload_key: String) {
|
||||
async fn s3_upload(&mut self, client: &Client, s3_upload_key: &str) {
|
||||
let key = format!("{s3_upload_key}{}", &self.name);
|
||||
self.s3_key = key.clone();
|
||||
let url: String = Client::new().put_object(&self.tmp_path, &key.clone()).await;
|
||||
let url = client.put_object(&self.tmp_path, &key.clone()).await;
|
||||
self.s3_url = url;
|
||||
}
|
||||
|
||||
fn tmp_remove(&self) {
|
||||
std::fs::remove_file(&self.tmp_path).unwrap();
|
||||
fs::remove_file(&self.tmp_path).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn split_payload(payload: &mut Multipart) -> (Bytes, Vec<Tmpfile>) {
|
||||
let mut tmp_files: Vec<Tmpfile> = Vec::new();
|
||||
let mut tmp_files = vec![];
|
||||
let mut data = Bytes::new();
|
||||
|
||||
while let Some(item) = payload.next().await {
|
||||
@ -80,7 +81,7 @@ pub async fn split_payload(payload: &mut Multipart) -> (Bytes, Vec<Tmpfile>) {
|
||||
Some(filename) => {
|
||||
let tmp_file = Tmpfile::new(&sanitize_filename::sanitize(&filename));
|
||||
let tmp_path = tmp_file.tmp_path.clone();
|
||||
let mut f = web::block(move || std::fs::File::create(&tmp_path))
|
||||
let mut f = web::block(move || fs::File::create(&tmp_path))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
@ -103,24 +104,27 @@ pub async fn split_payload(payload: &mut Multipart) -> (Bytes, Vec<Tmpfile>) {
|
||||
}
|
||||
|
||||
pub async fn save_file(
|
||||
client: &Client,
|
||||
tmp_files: Vec<Tmpfile>,
|
||||
s3_upload_key: String,
|
||||
s3_upload_key: &str,
|
||||
) -> Result<Vec<UploadFile>, Error> {
|
||||
let mut arr: Vec<UploadFile> = Vec::with_capacity(tmp_files.len());
|
||||
|
||||
for item in tmp_files {
|
||||
let mut tmp_file: Tmpfile = item.clone();
|
||||
|
||||
tmp_file
|
||||
.s3_upload_and_tmp_remove(s3_upload_key.clone())
|
||||
.s3_upload_and_tmp_remove(client, s3_upload_key)
|
||||
.await;
|
||||
|
||||
arr.push(UploadFile::from(tmp_file));
|
||||
}
|
||||
Ok(arr)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub async fn delete_object(list: Vec<String>) {
|
||||
for key in list {
|
||||
Client::new().delete_object(key).await;
|
||||
pub async fn delete_object(client: &Client, keys: Vec<&str>) {
|
||||
for key in keys {
|
||||
client.delete_object(key).await;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user