问题描述
有很多关于如何使用 Phoenix 执行此操作的信息,但在我了解有关 Elixir 工作原理的更多信息之前,我有意避免使用 Phoenix。
为此,我有以下 Plug.Router
路径:
defmodule ElixirHttpServer do
use Plug.Router
use Plug.ErrorHandler
plug(Plug.Parsers,parsers: [:urlencoded,{:multipart,length: 1_000_000_000}])
plug(Plug.Logger)
plug(:match)
plug(:dispatch)
post "/upload" do
IO.inspect(Plug.Conn.read_body(conn),label: "body")
send_resp(conn,201,"Uploaded")
end
end
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file">
<input type="submit">
</form>
通过此表单上传文件时,我从 IO.inspect(Plug.Conn.read_body(conn))
获得以下输出:
18:11:13.097 [info] POST /upload [205/3062]
body: {:ok,"",%Plug.Conn{
adapter: {Plug.Cowboy.Conn,:...},assigns: %{},before_send: [#Function<1.128679493/1 in Plug.Logger.call/2>],body_params: %{},cookies: %Plug.Conn.Unfetched{aspect: :cookies},halted: false,host: "localhost",method: "POST",owner: #PID<0.750.0>,params: %{},path_info: ["upload"],path_params: %{},port: 8080,private: %{
plug_multipart: :done,plug_route: {"/upload",#Function<1.2199674/2 in ElixirHttpServer.do_match/4>}
},query_params: %{},query_string: "",remote_ip: {127,1},req_cookies: %Plug.Conn.Unfetched{aspect: :cookies},req_headers: [
{"accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"},{"accept-encoding","gzip,deflate,br"},{"accept-language","en-US,en;q=0.9"},{"cache-control","no-cache"},{"connection","keep-alive"},{"content-length","44"},{"content-type","multipart/form-data; boundary=----WebKitFormBoundary4wTVqggydpkBg30n"},{"host","localhost:8080"},{"origin","http://localhost:8080"},{"pragma",{"referer","http://localhost:8080/"},{"sec-ch-ua","\" Not;A Brand\";v=\"99\",\"Google Chrome\";v=\"91\",\"Chromium\";v=\"91\""},{"sec-ch-ua-mobile","?0"},{"sec-fetch-dest","document"},{"sec-fetch-mode","navigate"},{"sec-fetch-site","same-origin"},{"sec-fetch-user","?1"},{"upgrade-insecure-requests","1"},{"user-agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/91.0.4472.114 Safari/537.36"}
],request_path: "/upload",resp_body: nil,resp_cookies: %{},resp_headers: [{"cache-control","max-age=0,private,must-revalidate"}],scheme: :http,script_name: [],secret_key_base: nil,state: :unset,status: nil
}}
18:11:13.099 [info] Sent 201 in 2ms
我已多次通读 Plug.Upload 文档,但它似乎主要是您可以使用的结构。
Plug.Parsers 文档说明如下,但我不知道“启动 :plug
应用程序”的实际含义:
文件处理
如果文件是通过任何解析器上传的,Plug 将流式传输 将内容上传到临时目录中的文件以避免 将整个文件加载到内存中。对于这种情况, :plug 应用程序 需要启动才能使文件上传工作。更多详情 如何处理上传的文件可以在文档中找到 插件。上传。
上传文件时,标识该文件的请求参数 文件将是一个 Plug.Upload 结构,其中包含有关上传的信息 文件(例如文件名和内容类型)以及文件的位置 存储。
我在 :plug
中添加了 extra_applications
,但这似乎没有任何改变:
def application do
[
extra_applications: [:plug,:plug_cowboy,:logger],mod: {ElixirHttpServer.Application,[]}
]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:plug_cowboy,"~> 2.4"},{:hackney,"~> 1.17.0"},{:ex_aws,"~> 2.1"},{:ex_aws_s3,"~> 2.0"},{:configparser_ex,"~> 4.0"},{:sweet_xml,"~> 0.6"}
]
end
end
作为参考,这是我的主管申请:
defmodule ElixirHttpServer.Application do
@moduledoc "OTP application for S3 bucket list/upload"
use Application
require Logger
def start(_type,_args) do
children = [
{Plug.Cowboy,plug: ElixirHttpServer,options: [port: cowboy_port()]}
]
opts = [strategy: :one_for_one,name: ElixirHttpServer.Supervisor]
Logger.info("Starting the application...")
Supervisor.start_link(children,opts)
end
defp cowboy_port(),do: Application.get_env(:elixir_http_server,:cowboy_port,8080)
end
解决方法
我遗漏了 dist\App.exe install
dist\App.exe start
元素的 name
属性。
input type="file"
成功了。