我正在尝试实现一个HTML5输入字段,允许用户选择要上传的多个文件。我的表格中有以下内容:
<form method="post" enctype="multipart/form-data" action="index.cfm">
<input type="file" name="Images" id="Images" multiple="multiple" accept="image/jpeg, image/gif, image/png, application/zip" />
...
我可以在浏览器中选择多个文件,然后点击上传,但我不知道如何使用ColdFusion处理表单帖子。我认为以下内容可行,但这只会上传我选择的最后一个文件:
<cfloop list="#attributes.Images#" index="Image">
<cffile
destination = "#ExpandPath(Trim(request.TempFolder))#"
filefield = "Images"
action = "upload"
nameconflict = "MakeUnique"
result = "UploadedTempFile"
>
<cfoutput>#UploadedTempFile.serverFile#<br /></cfoutput>
</cfloop>
有人可以向我解释如何遍历通过我的一个表单字段提交的所有文件,以便我可以单独处理这些文件吗?
答案 0 :(得分:5)
在搜索了一些博客文章,绊倒了这篇文章并阅读了Adobe的文档之后,CF10似乎不支持共识是“多个”文件上传支持(除非您正在执行Flash表单)。问题是 cffile 标记的“ uploadall ”值可能会上传所有文件,但您不会返回有关文件的结果数组。
这是我使用基础Java方法并在ACF 10中测试的函数。
<cffunction name="getUploadedFiles" access="public" returntype="struct"
hint="Gets the uploaded files, grouped by the field name">
<cfset var local = {
files = {},
types = "text/plain,text/csv,application/msexcel,application/vnd.ms-excel,application/octet-stream",
tempFiles = form.getTempFiles(),
idx = 0} />
<cfscript>
arrayEach(form.getPartsArray(), function (field) {
var local = {fieldName = field.getName(), destinationFile = ""};
// Make sure the field available in the form is also
// available for the temporary files
if (structKeyExists(tempFiles, fieldName)) {
// Create the files of field array if it doesn't exist
if (!structKeyExists(files, fieldName)) {
files[fieldName] = [];
}
// If only 1 file was uploaded, it won't be an array - so make it one
if (!isArray(tempFiles[fieldName])) {
tempFiles[fieldName] = [tempFiles[fieldName]];
}
// Check that the form part is a file and within our list of valid types
if (field.isFile() && listFindNoCase(types, field.getContentType())) {
// Compile details about the upload
arrayAppend(files[fieldName], {
file = tempFiles[fieldName][++idx],
filePart = field,
filename = field.getFileName(),
filepath = field.getFilePath(),
contentType = field.getContentType(),
tempFile = tempFiles[fieldName][idx].getPath()
});
}
}
});
</cfscript>
<cfreturn local.files />
</cffunction>
跟着注释,这只是遍历所有表单部分,查找文件,并创建包含一些有用文件详细信息的数组(并根据我的应用程序要求按特定内容类型进行过滤)。
然后,我创建了 uploadFile 函数,该函数接收 fieldName 和 destinationPath 参数。我根据传入的字段获取上传文件的数组,循环访问文件以确保目标文件路径不存在(如果是,则使其唯一),然后使用的内容写入目标文件从临时上传引用的java.io.File 对象。
<cffunction name="uploadFile" access="public" returntype="array"
hint="Uploads a file (or multiple files) from the form to the server">
<cfargument name="fieldName" type="string" required="true" />
<cfargument name="destinationPath" type="string" required="true" />
<cfset var local = {files = [], filepaths = [], allFiles = getUploadedFiles()} />
<cfif structKeyExists(local.allFiles, arguments.fieldName)>
<cfset local.files = local.allFiles[arguments.fieldName] />
</cfif>
<cfloop array="#local.files#" index="local.file">
<cfset local.file.destinationFile = arguments.destinationPath & local.file.fileName />
<cfif fileExists(local.file.destinationFile)>
<cfset local.file.destinationFile = listFirst(local.file.destinationFile, ".") & "_#getTickCount()#.csv" />
</cfif>
<cfset fileWrite(local.file.destinationFile, fileRead(local.file.file)) />
<cfset arrayAppend(local.filePaths, local.file.destinationFile) />
</cfloop>
<cfset setActiveFileName(local.filePaths[arrayLen(local.filePaths)]) />
<cfreturn local.filePaths />
</cffunction>
现在我可以完全控制所有正在上传的文件,并且可以处理所需的结果。
答案 1 :(得分:2)
UPDATE :从ColdFusion 9开始,这是真的。这已在ColdFusion 10中得到纠正。
所以结束我们的评论对话:
默认的ColdFusion行为无法实现这一点。 cffile
不支持从单个file
元素处理多个文件上传。我认为有可能回到JAVA这样做,但我不知道如何实现这一点。
我希望cffile action="uploadall"
能够获取所有HTML5多文件元素。需要将其作为CF10的ER提交:)。
答案 2 :(得分:1)
fileUploadAll()
/ <cffile action="uploadAll">
允许您上传所有文件,也可以上传<input type="file" multiple>
的多个文件。
尽管它始终处理请求的所有个文件,即,它不能区分不同的文件输入,您可能希望以不同的方式处理它们,例如通过accept
参数设置不同的允许的MIME类型,或为每次输入将文件上传到不同的位置。
因此,我在Adobe ColdFusion和Lucee issue tracker上创建了一个增强请求。
基本思想是,如果表单字段具有多个文件,或者如果这引起兼容性问题,则更改fileUpload()
函数和<cffile action="upload">
以自动返回一个数组,请添加一个新参数{{1} }默认为multiple
控制。