请注意,此方案主要依赖于某种XMLHTTPRequest约定,即POST的主体在请求之后的第二帧/后续帧中发送 . 如果不是这种情况,则代码需要在初始请求的有效负载中找到第一个\ r \ n \ r \ n,并将随后的数据附加到文件中 .
不用说,芯片必须在呼叫之前设置为AP .
headerBlock = "\r\nContent-type: text/html\r\nConnection: close\r\nAccess-Control-Allow-Origin: *\r\nCache-Control: no-cache\r\n\r\n"
local currentFileName = ""
local isPostData = false
print("filexfer")
local srv=net.createServer(net.TCP, 60)
srv:listen(80,
function(conn)
local function writefile(name, mode, data)
if (file.open("temp_" .. name, mode) == nil) then
return -1
end
file.write(data)
file.close()
end
conn:on("disconnection",
function(conn)
isPostData = false
end
)
conn:on("sent",
function(conn)
currentFileName = ""
isPostData = false
conn:close()
end
)
conn:on("receive",
function(conn, payload)
tmr.wdclr();
local s, e, m, buf, k, v
local tbl = {}
local i = 1
local retval = ""
if isPostData then
writefile(currentFileName, "a+", payload)
else
s, e = string.find(payload, "HTTP", 1, true)
if e ~= nil then
buf = string.sub(payload, 1, s - 2)
for m in string.gmatch(buf, "/?([%w+%p+][^/+]*)") do
tbl[i] = m
i = i + 1
end
m = nil
if #tbl > 2 then
local cmd = tbl[2]
if (tbl[3] ~= nil) and (tbl[3] ~= "/") then
currentFileName = tbl[3]
--else return an error
end
if (cmd == "put") then
writefile(currentFileName, "w+", "")
end
if (cmd == "append") then
isPostData = true
end
if (cmd == "persist") then
file.rename("temp_" .. currentFileName, currentFileName)
end
buf = ""
if retval == nil then
retval = "[nil]"
end
buf = "HTTP/1.1 200 OK" .. headerBlock .. retval
else
local filename = "index.html"
if tbl[2] ~= nil and tbl[2] ~= "/" then
filename = tbl[2]
end
require("fileupload")(conn, filename)
buf = ""
end
conn:send(buf)
end
end
end
)
end
)
local module =...
return function(conn, fname)
local buf
tmr.wdclr()
if file.list()[fname] ~= nil then
file.open(fname, "r")
buf = "HTTP/1.1 200 OK" .. headerBlock
else
file.open("error404.html", "r")
buf = "HTTP/1.1 404 FILE NOT FOUND" .. headerBlock
end
conn:on ("sent",
function(sck)
function sendfile(sck)
buf = file.read(255)
if buf ~= nil then
sck:send(buf)
else
sck:close()
if module ~= nil then
package.loaded[module] = nil
end
module = nil
return
end
end
sck:on("sent", sendfile)
sck:on("disconnection",
function(sck)
print("[disconnection fileupload.sendfile]", node.heap())
end
)
sendfile(sck)
end
)
conn:on ("receive",
function(sck, pl)
sck:close()
end
)
if buf == nil then
buf = ""
end
conn:send(buf)
end
5 回答
对的,这是可能的 . 它是一种自制的选择,但它在一定程度上起作用 . 当然,唯一的限制是尺寸,但除此之外它的效果非常好 . 看一眼:
http://www.instructables.com/id/ESP8266-WiFi-File-Management/
你需要有一种方法来编写PHP程序(我用C#编写),如果你不能用你能下载的另一种语言编写代码并重用这个用户编写的内容并使用你自己的PHP服务器而你应该很好走 .
如果您有任何疑问,请询问 .
我通过wifi上传所有模块 . 我首先以通常的方式(通过USB)上传一个
bootstrap.lua
程序 . 然后,该程序可用于上载实际(较大)有效载荷 . 这是引导程序:第一行使用网关服务器作为上载程序的Web服务器 . 第二行设置要上载的程序的端口(
80
),路径(/upload
)和名称(u.lc
) . 然后它获取文件并最终运行它(最后一行) .您必须在运行此无线连接之前激活无线连接,并且您的Web服务器当然应该处于活动状态,并且您的有效负载位于
/upload/u.lc
中 .当然,您可以更改硬连线值,甚至可以使它们动态化 .
Headers ##这应该是您想要的简单起点 .
顺便说一句,浓缩格式是为了使初始上传速度快,我使用
--dofile
选项上传luatool.py
.稍后更新程序(
u.lc
)是dofile("bootstrap.lua")
的简单重复 .我的
u.lc
是一个阶段2引导程序,它上传了一长串文件(主要是.lc
) . 对于这个简短的回答可能也太过牵扯 .最后,我应该提一下,这是基于https://github.com/Manawyrm/ESP8266-HTTP/
HTH
我有另一个解决方案,没有大小限制 . 此外,它不需要任何其他Web服务器,您可以直接从工作站发送文件 . 下面的文件提供了上传和下载到芯片的内容 .
不幸的是,它不使用Web浏览器使用的标准上载方案,最后提供了一个上传到它的javascript文件 . 可以在SendTo文件夹中创建js的快捷方式,从而将其添加到每个文件的上下文菜单中的“发送到”选项列表中,但它只能处理单个文件选择 . (处理选择的多个文件需要shell扩展 . )
它确实支持常规浏览器下载 .
请注意,此方案主要依赖于某种XMLHTTPRequest约定,即POST的主体在请求之后的第二帧/后续帧中发送 . 如果不是这种情况,则代码需要在初始请求的有效负载中找到第一个\ r \ n \ r \ n,并将随后的数据附加到文件中 .
不用说,芯片必须在呼叫之前设置为AP .
这是fileupload.lua,由要求接近第75行的调用引用(上载因为芯片正在将文件发送到请求主机 . )它使用常规浏览器便于下载任何大小的文件 . 如果没有传递文件名,则默认为“index.html” .
这是用于上传到芯片的客户端javascript文件 . 将要上载的文件的完整路径或相对路径作为其第一个/唯一参数传递 . (如果没有传递args,则会抛出错误 . )
上面描述了一种解决方案(http://www.instructables.com/id/ESP8266-WiFi-File-Management/),但使用桌面.NET应用程序代替PHP Web服务器https://github.com/Orudnev/.Net-WiFi-File-Manager-for-ESP8266 . 如果您不喜欢安装Web服务器可能会更方便,它足以启动FileManager.exe应用程序 .
如果您使用Esplorer作为IDE,则另一种方法是here
它使用ESP8266上的telnet服务器,并将Esplorer串口重定向到telnet服务器的地址;这是一个Windows示例,但我已经设法使用Linux下的“socat”工作 .
我发现的唯一问题是如果你想要多个tcp服务器,Nodemcu不允许,在这种情况下,可能另一个ESP8266充当tcp /串行控制台中继可能是答案 .