Copy link to clipboard
Copied
I'm using Lr 6.8 / Win10.
I have running code that uploads photo/videos to a WebService via LrHttp.post(). Basicly, the code is:
function PSUploadAPI.uploadPictureFile(...)
...
local respBody, respHeaders = LrHttp.post(h.serverUrl .. h.uploadPath, LrFileUtils.readFile(srcFilename), postHeaders, 'POST', timeout, fileSize)
...
Now, someone tried to upload a 11 minute FullHD/30fps AVCHD Video with a filesize of 2GB and ended up with:
Internal error: 'Attempt to seek past end of file'
So, I assume there is a size limit for LrFileUtils.readFile(). Looking for a solution I found this thread answered by John:
How to avoid LrStringUtils.encodeBase64 and LrFileUtils.readFile to block the main thread?
I reworked the code accordingly to use file:read():
local readFiles = {}
local function openFile(filename)
readFiles[filename] = io.open(filename, "rb")
end
local function readFileChunk(filename, nBytes)
if not readFiles[filename] then
writeLogfile(4, string.format("readFileChunk(%s, %d): file not opened\n", filename, nBytes))
return false
end
local readBuf = readFiles[filename]:read(nBytes)
if readBuf then
writeLogfile(4, string.format("readFileChunk(%s, %d) returns %d Bytes\n", filename, nBytes, #readBuf))
else
writeLogfile(4, string.format("readFileChunk(%s, %d) returns EOF\n", filename, nBytes))
endI
return readBuf
end
local function closeFile(filename)
io.close(readFiles[filename])
readFiles[filename] = nil
end
function PSUploadAPI.uploadPictureFile(...)
...
openFile(srcFilename)
local respBody, respHeaders = LrHttp.post(h.serverUrl .. h.uploadPath, readFileChunk(srcFilename, 10000), postHeaders, 'POST', timeout, fileSize)
closeFile(srcFilename)
I could verify that readFileChunk() works as expected (from LrHttp.post()), returning chunks of max 10.000 Bytes until EOF, when it returns nil. But for some reason LrHttp.post() is calling the callback function only once.
Questions:
Thanks, Martin
The code fragment you posted:
LrHttp.post(h.serverUrl .. h.uploadPath, readFileChunk(srcFilename, 10000),
is passing the result of calling readFileChunk() rather than a callback function. Thus, it is only getting called once. I think you'll probably want to do something like:
LrHttp.post(h.serverUrl .. h.uploadPath, function () return readFileChunk(srcFilename, 10000) end,
Copy link to clipboard
Copied
The code fragment you posted:
LrHttp.post(h.serverUrl .. h.uploadPath, readFileChunk(srcFilename, 10000),
is passing the result of calling readFileChunk() rather than a callback function. Thus, it is only getting called once. I think you'll probably want to do something like:
LrHttp.post(h.serverUrl .. h.uploadPath, function () return readFileChunk(srcFilename, 10000) end,
Copy link to clipboard
Copied
Hi John,
thanks for your prompt response, once again. I really appreciate your help!
Stupid me! You 're totally right, I wanted the chunk reader function to be used as callback not its result. The original code was misleading me. I'll check it in the evening, but I'm pretty sure it will work that way!
Thanks, Martin
Copy link to clipboard
Copied
When I used to be a developer and then a manager, one of my mottos was, "Two pairs of eyes".
Copy link to clipboard
Copied
Jep, sometimes it takes two pairs of eyes!
Works as expected. Using chunks of 10 MBytes seems to be slightly faster than using LrFileUtils.readFile() at least for large video files.
The code is quite straight forward after all:
local postFile = io.open(srcFilename, "rb")
if not postFile then return false end
local respBody, respHeaders = LrHttp.post(h.serverUrl .. h.uploadPath, function () return postFile:read(10000000) end, postHeaders, 'POST', timeout, fileSize)
postFile:close()
Thanks again!