//multipartFormData 上传文件表单 import fsys.mime; namespace web; class multipartFormData{ ctor(){ var formData = {}; var currentName,currentValue,currentFile; var boundary = "----------" + ..string.random( ..math.random(15,20) ); var endOfData; }; boundary = function(){ return boundary; }; contentType = function(){ return ..string.format('multipart/form-data; boundary=%s',boundary ) }; contentHeader = function(...){ return ..table.mix({ ["Content-Type"] = this.contentType() },...) }; add = function(name,value){ value = ( value === null ? "" : tostring(value) ); if(! (name && value) ) error("参数不能为空",2); formData[name] = value; }; addFile = function(name,value){ value = value ? tostring(value); if(! (name && value) ) error("参数不能为空",2); formData[name] = "@" + value; }; addTable = function(t){ for k,v in ..table.eachName(t) formData[k] = tostring(v); }; size = function() { var contentLength = 0; var testFileSize = function(size){ contentLength += size; } while( var s; s = this.read(,testFileSize); s ) { contentLength += #s; } return contentLength; }; read = function(blockSize=0x2000,testFileSize){ if( currentFile ){ if( !testFileSize ){ var s = currentFile.read(blockSize); if( s ) return s; } else { testFileSize( currentFile.size(1) ); } currentFile.close(); currentFile = null; return '\r\n'; } if( ( currentName === null) && endOfData ){ endOfData = null; return; } currentName,currentValue = ..table.next(formData,currentName); if( !currentName ) { endOfData = true; return ..string.format( '--%s--\r\n',boundary); } if( currentValue[1]=='@'# ){ var filePath = ..string.right(currentValue,-2); currentFile = ..io.file( filePath,"rb") if(!currentFile) return ""; var mime = ..fsys.mime.fromFile(filePath); var tPath = ..io.splitpath(filePath); var filename = tPath.file; filename = ( (this.codePage!==null) ? ..string.fromto(filename,65001,this.codePage) : filename ) //rfc2388,RFC 2231 ? return ..string.format( '--%s\r\n Content-Disposition: form-data; name="%s"; filename="%s"\r\n Content-Type: %s\r\n\r\n',boundary,currentName,filename,mime :"application/octet-stream" ) } return ..string.format( '--%s\r\n Content-Disposition: form-data; name="%s"\r\n \r\n %s\r\n', boundary,currentName, ( (this.codePage!==null) ? ..string.fromto(currentValue,65001,this.codePage) : currentValue ) ) } readAll = function(blockSize){ var t = {}; while( var s; s = this.read(blockSize); s ) { ..table.push(t,s) } return ..string.join(t); } close = function(){ if( currentFile ){ currentFile.close(); currentFile = null; } } } ..math.randomize() /**intellisense() web.multipartFormData = web.multipartFormData 用于构建 `multipart/form-data` 格式的上传文件表单。\n如果需要解析此格式的数据请使用 fsys.multipartFormData 库。 web.multipartFormData() = 构建上传文件表单\n!webMultipartFormData. end intellisense**/ /**intellisense(!webMultipartFormData) codePage = 指定服务端编码使用的代码页\n数值,UTF8编码为65001,系统默认ANSI编码为0,null为默认UTF8编码 addFile(.("字段名","文件路径") = 添加文件到上传表单中 add(.("字段名","@值") = 添加字段到上传表单中\n如果值的第一个字符为"@",则@后面应当是上传文件路径 addTable(字段名值对) = @.addTable(\n [""] = "@__/*如果值的第一个字符为"@",则@后面应当是上传文件路径*/"; \n [""] = "";\n); size() = 获取上传数据总大小 read(.(块大小) = 读取上传数据\n应循环调用该函数,直到该函数返回空值 readAll(.(块大小) = 读取所有数据 contentType() = 返回请求HTTP头Content-Type的值:\n"multipart/form-data; boundary=分隔符" contentHeader() = 返回一个用于构建HTTP头的表,指定了Content-Type的值:\n"multipart/form-data; boundary=分隔符"\n\n可选在参数中指定多个附加表用于添加更多键值 close() = 关闭对象\n无需手动调用该函数 end intellisense**/