ColdFusion处理HTML5 <input type =“file”multiple =“multiple”/>

时间:2011-09-07 18:10:43

标签: html5 file-upload file-io coldfusion

我正在尝试实现一个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>

有人可以向我解释如何遍历通过我的一个表单字段提交的所有文件,以便我可以单独处理这些文件吗?

3 个答案:

答案 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 ColdFusionLucee issue tracker上创建了一个增强请求。

基本思想是,如果表单字段具有多个文件,或者如果这引起兼容性问题,则更改fileUpload()函数和<cffile action="upload">以自动返回一个数组,请添加一个新参数{{1} }默认为multiple控制。