mirror of
https://github.com/actix/examples
synced 2024-11-27 07:52:57 +01:00
update multipart examples to use derive macro
This commit is contained in:
parent
9b77b033b0
commit
080db60175
289
Cargo.lock
generated
289
Cargo.lock
generated
@ -222,20 +222,40 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "actix-multipart"
|
||||
version = "0.4.0"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9edfb0e7663d7fe18c8d5b668c9c1bcf79176b1dcc9d4da9592503209a6bfb0"
|
||||
checksum = "dee489e3c01eae4d1c35b03c4493f71cb40d93f66b14558feb1b1a807671cc4e"
|
||||
dependencies = [
|
||||
"actix-multipart-derive",
|
||||
"actix-utils",
|
||||
"actix-web",
|
||||
"bytes 1.4.0",
|
||||
"derive_more",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"httparse",
|
||||
"local-waker",
|
||||
"log",
|
||||
"memchr",
|
||||
"mime",
|
||||
"twoway",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_plain",
|
||||
"tempfile",
|
||||
"tokio 1.25.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-multipart-derive"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ec592f234db8a253cf80531246a4407c8a70530423eea80688a6c5a44a110e7"
|
||||
dependencies = [
|
||||
"darling 0.14.3",
|
||||
"parse-size",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -816,6 +836,17 @@ dependencies = [
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "assert-json-diff"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4259cbe96513d2f1073027a259fc2ca917feb3026a5a8d984e3628e490255cc0"
|
||||
dependencies = [
|
||||
"extend",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-channel"
|
||||
version = "1.8.0"
|
||||
@ -1067,10 +1098,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-config"
|
||||
version = "0.52.0"
|
||||
version = "0.54.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7688e1dfbb9f7804fab0a830820d7e827b8d973906763cf1a855ce4719292f5"
|
||||
checksum = "3c3d1e2a1f1ab3ac6c4b884e37413eaa03eb9d901e4fc68ee8f5c1d49721680e"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-http",
|
||||
"aws-sdk-sso",
|
||||
"aws-sdk-sts",
|
||||
@ -1094,10 +1126,23 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-endpoint"
|
||||
version = "0.52.0"
|
||||
name = "aws-credential-types"
|
||||
version = "0.54.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "253d7cd480bfa59a5323390e9e91885a8f06a275e0517d81eeb1070b6aa7d271"
|
||||
checksum = "bb0696a0523a39a19087747e4dafda0362dc867531e3d72a3f195564c84e5e08"
|
||||
dependencies = [
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-types",
|
||||
"tokio 1.25.0",
|
||||
"tracing",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-endpoint"
|
||||
version = "0.54.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80a4f935ab6a1919fbfd6102a80c4fccd9ff5f47f94ba154074afe1051903261"
|
||||
dependencies = [
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-types",
|
||||
@ -1109,10 +1154,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-http"
|
||||
version = "0.52.0"
|
||||
version = "0.54.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cd1b83859383e46ea8fda633378f9f3f02e6e3a446fd89f0240b5c3662716c9"
|
||||
checksum = "82976ca4e426ee9ca3ffcf919d9b2c8d14d0cd80d43cc02173737a8f07f28d4d"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-types",
|
||||
"aws-types",
|
||||
@ -1127,10 +1173,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-sdk-s3"
|
||||
version = "0.22.0"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4d240ff751efc65099d18f6b0fb80360b31a298cec7b392c511692bec4a6e21"
|
||||
checksum = "1533be023eeac69668eb718b1c48af7bd5e26305ed770553d2877ab1f7507b68"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-endpoint",
|
||||
"aws-http",
|
||||
"aws-sig-auth",
|
||||
@ -1141,6 +1188,7 @@ dependencies = [
|
||||
"aws-smithy-eventstream",
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-http-tower",
|
||||
"aws-smithy-json",
|
||||
"aws-smithy-types",
|
||||
"aws-smithy-xml",
|
||||
"aws-types",
|
||||
@ -1149,17 +1197,22 @@ dependencies = [
|
||||
"fastrand",
|
||||
"http",
|
||||
"http-body 0.4.5",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"regex",
|
||||
"tokio-stream",
|
||||
"tower",
|
||||
"tracing",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-sdk-sso"
|
||||
version = "0.22.0"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf03342c2b3f52b180f484e60586500765474f2bfc7dcd4ffe893a7a1929db1d"
|
||||
checksum = "ca0119bacf0c42f587506769390983223ba834e605f049babe514b2bd646dbb2"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-endpoint",
|
||||
"aws-http",
|
||||
"aws-sig-auth",
|
||||
@ -1172,16 +1225,18 @@ dependencies = [
|
||||
"aws-types",
|
||||
"bytes 1.4.0",
|
||||
"http",
|
||||
"regex",
|
||||
"tokio-stream",
|
||||
"tower",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-sdk-sts"
|
||||
version = "0.22.0"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa1de4e07ea87a30a317c7b563b3a40fd18a843ad794216dda81672b6e174bce"
|
||||
checksum = "270b6a33969ebfcb193512fbd5e8ee5306888ad6c6d5d775cdbfb2d50d94de26"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-endpoint",
|
||||
"aws-http",
|
||||
"aws-sig-auth",
|
||||
@ -1189,22 +1244,25 @@ dependencies = [
|
||||
"aws-smithy-client",
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-http-tower",
|
||||
"aws-smithy-json",
|
||||
"aws-smithy-query",
|
||||
"aws-smithy-types",
|
||||
"aws-smithy-xml",
|
||||
"aws-types",
|
||||
"bytes 1.4.0",
|
||||
"http",
|
||||
"regex",
|
||||
"tower",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-sig-auth"
|
||||
version = "0.52.0"
|
||||
version = "0.54.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6126c4ff918e35fb9ae1bf2de71157fad36f0cc6a2b1d0f7197ee711713700fc"
|
||||
checksum = "660a02a98ab1af83bd8d714afbab2d502ba9b18c49e7e4cddd6bf8837ff778cb"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-sigv4",
|
||||
"aws-smithy-eventstream",
|
||||
"aws-smithy-http",
|
||||
@ -1215,9 +1273,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-sigv4"
|
||||
version = "0.52.0"
|
||||
version = "0.54.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84c7f88d7395f5411c6eef5889b6cd577ce6b677af461356cbfc20176c26c160"
|
||||
checksum = "cdaf11005b7444e6cd66f600d09861a3aeb6eb89a0f003c7c9820dbab2d15297"
|
||||
dependencies = [
|
||||
"aws-smithy-eventstream",
|
||||
"aws-smithy-http",
|
||||
@ -1236,9 +1294,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-async"
|
||||
version = "0.52.0"
|
||||
version = "0.54.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e6a895d68852dd1564328e63ef1583e5eb307dd2a5ebf35d862a5c402957d5e"
|
||||
checksum = "63c712a28a4f2f2139759235c08bf98aca99d4fdf1b13c78c5f95613df0a5db9"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"pin-project-lite 0.2.9",
|
||||
@ -1248,9 +1306,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-checksums"
|
||||
version = "0.52.0"
|
||||
version = "0.54.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b847d960abc993319d77b52e82971e2bbdce94f6192df42142e14ed5c9c917"
|
||||
checksum = "a3875fb4b28606a5368a048016a28c15707f2b21238d5b2e4a23198f590e92c4"
|
||||
dependencies = [
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-types",
|
||||
@ -1269,13 +1327,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-client"
|
||||
version = "0.52.0"
|
||||
version = "0.54.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f505bf793eb3e6d7c166ef1275c27b4b2cd5361173fe950ac8e2cfc08c29a7ef"
|
||||
checksum = "104ca17f56cde00a10207169697dfe9c6810db339d52fb352707e64875b30a44"
|
||||
dependencies = [
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-http-tower",
|
||||
"aws-smithy-protocol-test",
|
||||
"aws-smithy-types",
|
||||
"bytes 1.4.0",
|
||||
"fastrand",
|
||||
@ -1285,6 +1344,7 @@ dependencies = [
|
||||
"hyper-rustls",
|
||||
"lazy_static",
|
||||
"pin-project-lite 0.2.9",
|
||||
"serde",
|
||||
"tokio 1.25.0",
|
||||
"tower",
|
||||
"tracing",
|
||||
@ -1292,9 +1352,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-eventstream"
|
||||
version = "0.52.0"
|
||||
version = "0.54.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d751c99da757aecc1408ab6b2d65e9493220a5e7a68bcafa4f07b6fd1bc473f1"
|
||||
checksum = "ac250d8c0e42af0097a6837ffc5a6fb9f8ba4107bb53124c047c91bc2a58878f"
|
||||
dependencies = [
|
||||
"aws-smithy-types",
|
||||
"bytes 1.4.0",
|
||||
@ -1303,9 +1363,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-http"
|
||||
version = "0.52.0"
|
||||
version = "0.54.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37e4b4304b7ea4af1af3e08535100eb7b6459d5a6264b92078bf85176d04ab85"
|
||||
checksum = "873f316f1833add0d3aa54ed1b0cd252ddd88c792a0cf839886400099971e844"
|
||||
dependencies = [
|
||||
"aws-smithy-eventstream",
|
||||
"aws-smithy-types",
|
||||
@ -1326,9 +1386,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-http-tower"
|
||||
version = "0.52.0"
|
||||
version = "0.54.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e86072ecc4dc4faf3e2071144285cfd539263fe7102b701d54fb991eafb04af8"
|
||||
checksum = "4f38231d3f5dac9ac7976f44e12803add1385119ffca9e5f050d8e980733d164"
|
||||
dependencies = [
|
||||
"aws-smithy-http",
|
||||
"aws-smithy-types",
|
||||
@ -1342,18 +1402,33 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-json"
|
||||
version = "0.52.0"
|
||||
version = "0.54.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e3ddd9275b167bc59e9446469eca56177ec0b51225632f90aaa2cd5f41c940e"
|
||||
checksum = "4bd83ff2b79e9f729746fcc8ad798676b68fe6ea72986571569a5306a277a182"
|
||||
dependencies = [
|
||||
"aws-smithy-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-query"
|
||||
version = "0.52.0"
|
||||
name = "aws-smithy-protocol-test"
|
||||
version = "0.54.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13b19d2e0b3ce20e460bad0d0d974238673100edebba6978c2c1aadd925602f7"
|
||||
checksum = "d4d1c9bcb35ce11055ec128dab2c66a7ed47e2dfff99883e32c21a1ab6d6bee6"
|
||||
dependencies = [
|
||||
"assert-json-diff",
|
||||
"http",
|
||||
"pretty_assertions",
|
||||
"regex",
|
||||
"roxmltree",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-query"
|
||||
version = "0.54.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2f0445dafe9d2cd50b44339ae3c3ed46549aad8ac696c52ad660b3e7ae8682b"
|
||||
dependencies = [
|
||||
"aws-smithy-types",
|
||||
"urlencoding",
|
||||
@ -1361,9 +1436,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-types"
|
||||
version = "0.52.0"
|
||||
version = "0.54.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "987b1e37febb9bd409ca0846e82d35299e572ad8279bc404778caeb5fc05ad56"
|
||||
checksum = "8161232eda10290f5136610a1eb9de56aceaccd70c963a26a260af20ac24794f"
|
||||
dependencies = [
|
||||
"base64-simd",
|
||||
"itoa 1.0.5",
|
||||
@ -1374,19 +1449,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-smithy-xml"
|
||||
version = "0.52.0"
|
||||
version = "0.54.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37ce3791e14eec75ffac851a5a559f1ce6b31843297f42cc8bfba82714a6a5d8"
|
||||
checksum = "343ffe9a9bb3f542675f4df0e0d5933513d6ad038ca3907ad1767ba690a99684"
|
||||
dependencies = [
|
||||
"xmlparser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-types"
|
||||
version = "0.52.0"
|
||||
version = "0.54.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c05adca3e2bcf686dd2c47836f216ab52ed7845c177d180c84b08522c1166a3"
|
||||
checksum = "f8f15b34253b68cde08e39b0627cc6101bcca64351229484b4743392c035d057"
|
||||
dependencies = [
|
||||
"aws-credential-types",
|
||||
"aws-smithy-async",
|
||||
"aws-smithy-client",
|
||||
"aws-smithy-http",
|
||||
@ -1394,7 +1470,6 @@ dependencies = [
|
||||
"http",
|
||||
"rustc_version 0.4.0",
|
||||
"tracing",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1451,11 +1526,12 @@ checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
|
||||
|
||||
[[package]]
|
||||
name = "base64-simd"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "781dd20c3aff0bd194fe7d2a977dd92f21c173891f3a03b677359e5fa457e5d5"
|
||||
checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195"
|
||||
dependencies = [
|
||||
"simd-abstraction",
|
||||
"outref",
|
||||
"vsimd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2307,6 +2383,16 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctr"
|
||||
version = "0.9.2"
|
||||
@ -2594,6 +2680,12 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diff"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.6"
|
||||
@ -2742,6 +2834,18 @@ version = "2.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||
|
||||
[[package]]
|
||||
name = "extend"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f47da3a72ec598d9c8937a7ebca8962a5c7a1f28444e38c2b33c771ba3f55f05"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fallible-iterator"
|
||||
version = "0.2.0"
|
||||
@ -3575,7 +3679,6 @@ dependencies = [
|
||||
"rustls-native-certs",
|
||||
"tokio 1.25.0",
|
||||
"tokio-rustls",
|
||||
"webpki-roots 0.22.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4579,7 +4682,9 @@ version = "1.0.0"
|
||||
dependencies = [
|
||||
"actix-multipart",
|
||||
"actix-web",
|
||||
"env_logger",
|
||||
"futures-util",
|
||||
"log",
|
||||
"sanitize-filename",
|
||||
"uuid 1.3.0",
|
||||
]
|
||||
@ -4904,10 +5009,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
||||
|
||||
[[package]]
|
||||
name = "outref"
|
||||
version = "0.1.0"
|
||||
name = "output_vt100"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f222829ae9293e33a9f5e9f440c6760a3d450a64affe1846486b140db81c1f4"
|
||||
checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
|
||||
dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "outref"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4030760ffd992bef45b0ae3f10ce1aba99e33464c90d14dd7c039884963ddc7a"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
@ -4983,6 +5097,12 @@ dependencies = [
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parse-size"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "944553dd59c802559559161f9816429058b869003836120e262e8caec061b7ae"
|
||||
|
||||
[[package]]
|
||||
name = "parse-zoneinfo"
|
||||
version = "0.3.0"
|
||||
@ -5261,6 +5381,18 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
|
||||
[[package]]
|
||||
name = "pretty_assertions"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755"
|
||||
dependencies = [
|
||||
"ctor",
|
||||
"diff",
|
||||
"output_vt100",
|
||||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.1.23"
|
||||
@ -5816,6 +5948,15 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "roxmltree"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "921904a62e410e37e215c40381b7117f830d9d89ba60ab5236170541dd25646b"
|
||||
dependencies = [
|
||||
"xmlparser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "run-in-thread"
|
||||
version = "1.0.0"
|
||||
@ -6253,6 +6394,15 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_plain"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6018081315db179d0ce57b1fe4b62a12a0028c9cf9bbef868c9cf477b3c34ae"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.1"
|
||||
@ -6376,15 +6526,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simd-abstraction"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cadb29c57caadc51ff8346233b5cec1d240b68ce55cf1afc764818791876987"
|
||||
dependencies = [
|
||||
"outref",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simple-auth-server"
|
||||
version = "1.0.0"
|
||||
@ -7631,16 +7772,6 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
||||
|
||||
[[package]]
|
||||
name = "twoway"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c57ffb460d7c24cd6eda43694110189030a3d1dfe418416d9468fd1c1d290b47"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"unchecked-index",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "twox-hash"
|
||||
version = "1.6.3"
|
||||
@ -7693,12 +7824,6 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unchecked-index"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c"
|
||||
|
||||
[[package]]
|
||||
name = "unic-char-property"
|
||||
version = "0.9.0"
|
||||
@ -8020,6 +8145,12 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "vsimd"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.2"
|
||||
@ -8479,6 +8610,12 @@ dependencies = [
|
||||
"linked-hash-map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
||||
|
||||
[[package]]
|
||||
name = "yansi-term"
|
||||
version = "0.1.2"
|
||||
|
@ -74,7 +74,8 @@ actix-cors = "0.6"
|
||||
actix-files = "0.6"
|
||||
actix-http = "3"
|
||||
actix-identity = "0.5"
|
||||
actix-multipart = "0.4"
|
||||
actix-multipart = "0.6"
|
||||
actix-multipart-derive = "0.6"
|
||||
actix-protobuf = "0.9"
|
||||
actix-session = "0.7"
|
||||
actix-test = "0.1"
|
||||
|
@ -8,8 +8,8 @@ actix-multipart.workspace = true
|
||||
actix-web.workspace = true
|
||||
actix-web-lab.workspace = true
|
||||
|
||||
aws-config = "0.52"
|
||||
aws-sdk-s3 = "0.22"
|
||||
aws-config = "0.54"
|
||||
aws-sdk-s3 = "0.24"
|
||||
|
||||
dotenv = "0.15"
|
||||
env_logger.workspace = true
|
||||
|
@ -71,14 +71,16 @@ impl Client {
|
||||
|
||||
async fn upload_and_remove(&self, file: TempFile, key_prefix: &str) -> UploadedFile {
|
||||
let uploaded_file = self.upload(&file, key_prefix).await;
|
||||
file.delete_from_disk().await;
|
||||
tokio::fs::remove_file(file.file.path()).await.unwrap();
|
||||
uploaded_file
|
||||
}
|
||||
|
||||
async fn upload(&self, file: &TempFile, key_prefix: &str) -> UploadedFile {
|
||||
let filename = file.name();
|
||||
let key = format!("{key_prefix}{}", file.name());
|
||||
let s3_url = self.put_object_from_file(file.path(), &key).await;
|
||||
let filename = file.file_name.as_deref().expect("TODO");
|
||||
let key = format!("{key_prefix}{filename}");
|
||||
let s3_url = self
|
||||
.put_object_from_file(file.file.path().to_str().unwrap(), &key)
|
||||
.await;
|
||||
UploadedFile::new(filename, key, s3_url)
|
||||
}
|
||||
|
||||
|
@ -19,10 +19,7 @@
|
||||
|
||||
const formData = new FormData();
|
||||
|
||||
const meta = { namespace: $form.namespace.value };
|
||||
console.log(meta);
|
||||
|
||||
formData.append("meta", JSON.stringify(meta));
|
||||
formData.append("namespace", $form.namespace.value);
|
||||
|
||||
for (const file in $files.files) {
|
||||
formData.append("file", file);
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::fs;
|
||||
|
||||
use actix_multipart::Multipart;
|
||||
use actix_multipart::form::{tempfile::TempFile, text::Text, MultipartForm};
|
||||
use actix_web::{
|
||||
body::SizedStream, delete, error, get, middleware::Logger, post, web, App, Error, HttpResponse,
|
||||
HttpServer, Responder,
|
||||
@ -8,51 +8,41 @@ use actix_web::{
|
||||
use actix_web_lab::{extract::Path, respond::Html};
|
||||
use aws_config::meta::region::RegionProviderChain;
|
||||
use dotenv::dotenv;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
|
||||
mod client;
|
||||
mod temp_file;
|
||||
mod upload_file;
|
||||
mod utils;
|
||||
|
||||
use self::{client::Client, temp_file::TempFile, upload_file::UploadedFile, utils::split_payload};
|
||||
use self::{client::Client, upload_file::UploadedFile};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UploadMeta {
|
||||
namespace: String,
|
||||
}
|
||||
#[derive(Debug, MultipartForm)]
|
||||
struct UploadForm {
|
||||
namespace: Text<String>,
|
||||
|
||||
impl Default for UploadMeta {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
namespace: "default".to_owned(),
|
||||
}
|
||||
}
|
||||
#[multipart(rename = "file")]
|
||||
files: Vec<TempFile>,
|
||||
}
|
||||
|
||||
#[post("/")]
|
||||
async fn upload_to_s3(
|
||||
s3_client: web::Data<Client>,
|
||||
mut payload: Multipart,
|
||||
MultipartForm(form): MultipartForm<UploadForm>,
|
||||
) -> Result<impl Responder, Error> {
|
||||
let (data, files) = split_payload(&mut payload).await;
|
||||
log::info!("bytes = {data:?}");
|
||||
let namespace = form.namespace.into_inner();
|
||||
let files = form.files;
|
||||
|
||||
let upload_meta = serde_json::from_slice::<UploadMeta>(&data).unwrap_or_default();
|
||||
log::info!("converter_struct = {upload_meta:?}");
|
||||
log::info!("namespace = {namespace:?}");
|
||||
log::info!("tmp_files = {files:?}");
|
||||
|
||||
// make key prefix (make sure it ends with a forward slash)
|
||||
let s3_key_prefix = format!("uploads/{}/", upload_meta.namespace);
|
||||
let s3_key_prefix = format!("uploads/{namespace}/");
|
||||
|
||||
// create tmp file and upload s3 and remove tmp file
|
||||
// upload temp files to s3 and then remove them
|
||||
let uploaded_files = s3_client.upload_files(files, &s3_key_prefix).await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(json!({
|
||||
"uploadedFiles": uploaded_files,
|
||||
"meta": upload_meta,
|
||||
"meta": json!({ "namespace": namespace }),
|
||||
})))
|
||||
}
|
||||
|
||||
|
@ -1,35 +0,0 @@
|
||||
use tokio::fs;
|
||||
|
||||
/// Info for a temporary file to be uploaded to S3.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TempFile {
|
||||
path: String,
|
||||
name: String,
|
||||
}
|
||||
|
||||
impl TempFile {
|
||||
/// Constructs info container with sanitized file name.
|
||||
pub fn new(filename: &str) -> TempFile {
|
||||
let filename = sanitize_filename::sanitize(filename);
|
||||
|
||||
TempFile {
|
||||
path: format!("./tmp/{filename}"),
|
||||
name: filename,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns name of temp file.
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
/// Returns path to temp file.
|
||||
pub fn path(&self) -> &str {
|
||||
&self.path
|
||||
}
|
||||
|
||||
/// Deletes temp file from disk.
|
||||
pub async fn delete_from_disk(self) {
|
||||
fs::remove_file(&self.path).await.unwrap();
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
use actix_multipart::{Field, Multipart};
|
||||
use actix_web::web::{Bytes, BytesMut};
|
||||
use futures_util::StreamExt as _;
|
||||
use tokio::{fs, io::AsyncWriteExt as _};
|
||||
|
||||
use crate::TempFile;
|
||||
|
||||
/// Returns tuple of `meta` field contents and a list of temp file info to upload.
|
||||
pub async fn split_payload(payload: &mut Multipart) -> (Bytes, Vec<TempFile>) {
|
||||
let mut meta = Bytes::new();
|
||||
let mut temp_files = vec![];
|
||||
|
||||
while let Some(item) = payload.next().await {
|
||||
let mut field = item.expect("split_payload err");
|
||||
let cd = field.content_disposition();
|
||||
|
||||
if matches!(cd.get_name(), Some(name) if name == "meta") {
|
||||
// if field name is "meta", just collect those bytes in-memory and return them later
|
||||
meta = collect_meta(&mut field).await;
|
||||
} else {
|
||||
match cd.get_filename() {
|
||||
Some(filename) => {
|
||||
// if file has a file name, we stream the field contents into a temp file on
|
||||
// disk so that large uploads do not exhaust memory
|
||||
|
||||
// create file info
|
||||
let file_info = TempFile::new(filename);
|
||||
|
||||
// create file on disk from file info
|
||||
let mut file = fs::File::create(file_info.path()).await.unwrap();
|
||||
|
||||
// stream field contents to file
|
||||
while let Some(chunk) = field.next().await {
|
||||
let data = chunk.unwrap();
|
||||
file.write_all(&data).await.unwrap();
|
||||
}
|
||||
|
||||
// return file info
|
||||
temp_files.push(file_info);
|
||||
}
|
||||
|
||||
None => {
|
||||
log::warn!("field {:?} is not a file", cd.get_name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(meta, temp_files)
|
||||
}
|
||||
|
||||
async fn collect_meta(field: &mut Field) -> Bytes {
|
||||
let mut buf = BytesMut::new();
|
||||
|
||||
while let Some(chunk) = field.next().await {
|
||||
let chunk = chunk.expect("split_payload err chunk");
|
||||
buf.extend(chunk);
|
||||
}
|
||||
|
||||
buf.freeze()
|
||||
}
|
@ -12,6 +12,8 @@ readme = "README.md"
|
||||
actix-multipart.workspace = true
|
||||
actix-web.workspace = true
|
||||
|
||||
env_logger.workspace = true
|
||||
futures-util.workspace = true
|
||||
log.workspace = true
|
||||
sanitize-filename = "0.4"
|
||||
uuid = { version = "1", features = ["v4"] }
|
||||
|
@ -1,11 +1,77 @@
|
||||
use std::io::Write;
|
||||
|
||||
use actix_multipart::Multipart;
|
||||
use actix_web::{middleware, web, App, Error, HttpResponse, HttpServer};
|
||||
use actix_multipart::{
|
||||
form::{
|
||||
tempfile::{TempFile, TempFileConfig},
|
||||
text::Text,
|
||||
MultipartForm,
|
||||
},
|
||||
Multipart,
|
||||
};
|
||||
use actix_web::{middleware, web, App, Error, HttpResponse, HttpServer, Responder};
|
||||
use futures_util::TryStreamExt as _;
|
||||
use uuid::Uuid;
|
||||
|
||||
async fn save_file(mut payload: Multipart) -> Result<HttpResponse, Error> {
|
||||
#[derive(Debug, MultipartForm)]
|
||||
struct UploadForm {
|
||||
#[multipart(rename = "file")]
|
||||
files: Vec<TempFile>,
|
||||
}
|
||||
|
||||
async fn save_files(
|
||||
MultipartForm(form): MultipartForm<UploadForm>,
|
||||
) -> Result<impl Responder, Error> {
|
||||
for f in form.files {
|
||||
let path = format!("./tmp/{}", f.file_name.unwrap());
|
||||
log::info!("saving to {path}");
|
||||
f.file.persist(path).unwrap();
|
||||
}
|
||||
|
||||
Ok(HttpResponse::Ok())
|
||||
}
|
||||
|
||||
async fn index() -> HttpResponse {
|
||||
let html = r#"<html>
|
||||
<head><title>Upload Test</title></head>
|
||||
<body>
|
||||
<form target="/" method="post" enctype="multipart/form-data">
|
||||
<input type="file" multiple name="file"/>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>"#;
|
||||
|
||||
HttpResponse::Ok().body(html)
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||
|
||||
log::info!("creating temporary upload directory");
|
||||
std::fs::create_dir_all("./tmp")?;
|
||||
|
||||
log::info!("starting HTTP server at http://localhost:8080");
|
||||
|
||||
HttpServer::new(|| {
|
||||
App::new()
|
||||
.wrap(middleware::Logger::default())
|
||||
.app_data(TempFileConfig::default().directory("./tmp"))
|
||||
.service(
|
||||
web::resource("/")
|
||||
.route(web::get().to(index))
|
||||
.route(web::post().to(save_files)),
|
||||
)
|
||||
})
|
||||
.bind(("127.0.0.1", 8080))?
|
||||
.workers(2)
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
|
||||
/// Example of the old manual way of processing multipart forms.
|
||||
#[allow(unused)]
|
||||
async fn save_file_manual(mut payload: Multipart) -> Result<HttpResponse, Error> {
|
||||
// iterate over multipart stream
|
||||
while let Some(mut field) = payload.try_next().await? {
|
||||
// A multipart/form-data stream has to contain `content_disposition`
|
||||
@ -28,34 +94,3 @@ async fn save_file(mut payload: Multipart) -> Result<HttpResponse, Error> {
|
||||
|
||||
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">
|
||||
<input type="file" multiple name="file"/>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>"#;
|
||||
|
||||
HttpResponse::Ok().body(html)
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
std::env::set_var("RUST_LOG", "info");
|
||||
std::fs::create_dir_all("./tmp")?;
|
||||
|
||||
HttpServer::new(|| {
|
||||
App::new().wrap(middleware::Logger::default()).service(
|
||||
web::resource("/")
|
||||
.route(web::get().to(index))
|
||||
.route(web::post().to(save_file)),
|
||||
)
|
||||
})
|
||||
.bind(("127.0.0.1", 8080))?
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user