7

重要:このスレッドで説明されている問題はかなり前にそのバージョンで修正されており、Springの後続のバージョンでは再現できなくなっているため、この質問は3.0.4より後のSpringバージョンではまったく役に立ちません。


Springバージョン3.0.2を使用しています。multiple="multiple"次のようなファイルブラウザの属性を使用して、複数のファイルをアップロードする必要があります。

<input type="file" id="myFile" name="myFile" multiple="multiple"/>

(そして、この回答で述べられているような複数のファイルブラウザを使用していないので、実際に試してみました)。

適切なjQueryプラグイン/ウィジェットが使用されていない限り、Internet Explorerのどのバージョンもこのアプローチをサポートしていませんが、今は気にしません(他のほとんどのブラウザーがこれをサポートしているため)。

これはcommonsfileuploadRequestMethod.POSTで正常に機能しますが、メソッドの使用に加えて、Springによってサポートおよび提案されている他のリクエストメソッドを適切な場所でRequestMethod.GET使用したいと思いますRequestMethod.PUTこれを行うために、この質問が示すようにうまくいくRequestMethod.DELETESpringを構成しました。HiddenHttpMethodFilter

ただし、ファイルブラウザで複数のファイルが選択されている場合でも、一度にアップロードできるファイルは1つだけです。Springコントローラークラスでは、メソッドは次のようにマップされます。

@RequestMapping(method={RequestMethod.POST}, value={"admin_side/Temp"})
public String onSubmit(@RequestParam("myFile") List<MultipartFile> files, @ModelAttribute("tempBean") TempBean tempBean, BindingResult error, Map model, HttpServletRequest request, HttpServletResponse response) throws IOException, FileUploadException {
    for (MultipartFile file : files) {
        System.out.println(file.getOriginalFilename());
    }
}

タイプのリクエストパラメータ@RequestParam("myFile") List<MultipartFile> filesを使用する場合でも(一度に1つのファイルのみを持つことができます)。ListMultipartFile


このブログで、複数のファイルで機能する可能性のある戦略を見つけることができました。私はそれを注意深く調べました。

セクションソリューション2ののソリューション–RAWリクエストを使用すると次のようになります。

ただし、クライアントが「files[]」や「files」などの同じフォーム入力名を使用し、その名前に複数のファイルを入力することを要求する場合は、次のように小さなハックが必要です。上記のように、Spring 2.5は、ファイルタイプの同じフォーム入力名を複数回検出した場合に例外をスローします。CommonsFileUploadSupportその例外をスローするクラスはfinalではなく、その例外をスローするメソッドは保護されているため、継承の驚異を使用してサブクラス化すると、次のようにロジックを少し修正/変更できます。私が行った変更は、文字通り1つのメソッド呼び出しを表す1つの単語であり、同じフォーム入力名で複数のファイルを受信できるようにします。

メソッドをオーバーライドしようとします

protected MultipartParsingResult parseFileItems(List fileItems, String encoding){}

次のようなクラスCommonsFileUploadSupportを拡張することによる抽象クラスのCommonsMultipartResolver

package multipartResolver;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import org.apache.commons.fileupload.FileItem;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

public final class MultiCommonsMultipartResolver extends CommonsMultipartResolver {

    public MultiCommonsMultipartResolver() {}

    public MultiCommonsMultipartResolver(ServletContext servletContext) {
        super(servletContext);
    }

    @Override
    @SuppressWarnings("unchecked")
    protected MultipartParsingResult parseFileItems(List fileItems, String encoding) {
        Map<String, MultipartFile> multipartFiles = new HashMap<String, MultipartFile>();
        Map multipartParameters = new HashMap();

        // Extract multipart files and multipart parameters.
        for (Iterator it = fileItems.iterator(); it.hasNext();) {
            FileItem fileItem = (FileItem) it.next();

            if (fileItem.isFormField()) {
                String value = null;

                if (encoding != null) {
                    try {
                        value = fileItem.getString(encoding);
                    } catch (UnsupportedEncodingException ex) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Could not decode multipart item '" + fileItem.getFieldName()
                                    + "' with encoding '" + encoding + "': using platform default");
                        }

                        value = fileItem.getString();
                    }
                } else {
                    value = fileItem.getString();
                }

                String[] curParam = (String[]) multipartParameters.get(fileItem.getFieldName());

                if (curParam == null) {
                    // simple form field
                    multipartParameters.put(fileItem.getFieldName(), new String[]{value});
                } else {
                    // array of simple form fields
                    String[] newParam = StringUtils.addStringToArray(curParam, value);
                    multipartParameters.put(fileItem.getFieldName(), newParam);
                }
            } else {
                // multipart file field
                CommonsMultipartFile file = new CommonsMultipartFile(fileItem);
                if (multipartFiles.put(fileItem.getName(), file) != null) {
                    throw new MultipartException("Multiple files for field name [" + file.getName()
                            + "] found - not supported by MultipartResolver");
                }

                if (logger.isDebugEnabled()) {
                    logger.debug("Found multipart file [" + file.getName() + "] of size " + file.getSize()
                            + " bytes with original filename [" + file.getOriginalFilename() + "], stored "
                            + file.getStorageDescription());
                }
            }
        }

        return new MultipartParsingResult(multipartFiles, multipartParameters);
    }
}

何が起こるかというと、メソッドの最後の行parseFileItems()(returnステートメント)、つまり

return new MultipartParsingResult(multipartFiles, multipartParameters);

最初のパラメータはによって実装されmultipartFilesたタイプであるため、コンパイル時エラーが発生しますが、実際には、タイプのパラメータが必要です。MapHashMap MultiValueMap<String, MultipartFile>

これは、抽象クラス内の静的クラスのコンストラクターですCommonsFileUploadSupport

public abstract class CommonsFileUploadSupport {
    protected static class MultipartParsingResult {
        public MultipartParsingResult(MultiValueMap<String, MultipartFile> mpFiles, Map<String, String[]> mpParams) {}
    }
}

理由はおそらく-この解決策はSpringバージョン2.5に関するものであり、私はSpringバージョン3.0.2を使用していますが、これはこのバージョンには不適切である可能性があります。


ただし、次のコードセグメントに示すようなさまざまな方法でMap、を置き換えようとしました。MultiValueMap

MultiValueMap<String, MultipartFile>mul=new LinkedMultiValueMap<String, MultipartFile>();   

for(Entry<String, MultipartFile>entry:multipartFiles.entrySet()) {
    mul.add(entry.getKey(), entry.getValue());
}

return new MultipartParsingResult(mul, multipartParameters);

しかし、成功しません。交換する方法がわかりません。交換MapするMultiValueMapこともできます。これを行った後、ブラウザはHttp応答を表示します。

HTTPステータス400-

タイプステータスレポート

メッセージ

descriptionクライアントから送信された要求は構文的に正しくありませんでした()。

Apache Tomcat / 6.0.26


質問をできるだけ短くするように努めましたが、不要なコードは含めていません。

Springを設定した後、どうすれば複数のファイルをアップロードできるようになりますHiddenHttpMethodFilterか?

そのブログは、それが長年の、優先度の高いバグであることを示しています。

バージョン3.0.2(3以降)に関する解決策がない場合は、Springサポートを永久に無効にし、そのブログの3番目の解決策で提案されているようにcommons-fileupoladを引き続き使用し、PUT、DELETE、およびその他の要求メソッドを永久に省略します。 。


parseFileItems()クラス内のメソッドのコードにほとんど変更を加えないと、MultiCommonsMultipartResolver 複数のファイルがアップロードされる可能性がありますが、試行に成功しませんでした(Springバージョン3.0.2(3以降)でも)。

4

2 に答える 2

3

1つのリクエストで複数のファイルをアップロードするために、次のコードを使用しました。

私はそのようなjspを持っています:

<p>Select files to upload. Press Add button to add more file inputs.</p>
<table>
    <tr>
        <td><input name="files" type="file" multiple="true"/></td>
    </tr>
    <tr>
        <td><input name="files" type="file" multiple="true"/></td>
    </tr>
</table>
<br/><input type="submit" value="Upload" />

ファイルアップロードクラスBean:

import org.springframework.web.multipart.commons.CommonsMultipartFile;

public class FileUploadForm {

    private CommonsMultipartFile [] files;

    public CommonsMultipartFile[] getFiles() {
        return files;
    }

    public void setFiles( CommonsMultipartFile[] files ) {
        this.files = files;
    }
}

コントローラ:

@Controller
@RequestMapping("/upload")
public class FileUploadController {

    @RequestMapping(method = RequestMethod.GET)
    public String displayForm(ModelMap modelMap) {
        modelMap.addAttribute( new FileUploadForm() );
        return "uploadForm.jsp";
    }

    @RequestMapping(method = RequestMethod.POST)
    public String save(FileUploadForm uploadForm) {
        CommonsMultipartFile[] files = uploadForm.getFiles();
        if(files != null && files.length != 0) {
            for(MultipartFile file : files) {
                System.out.println( file.getOriginalFilename() );
            }
        }
        return "success.jsp";
    }
}

このコードを使用すると、1つのリクエストで複数のファイルをアップロードでき、CommonsMultipartFile各ファイルのインスタンスを取得できます。

于 2013-03-23T21:32:17.973 に答える
1

質問に記載されている問題は、Spring3.0.4で修正されました。そのため、そのバージョン以降を使用した場合(はい、現在は4.xxです)、この質問/回答を読む必要はありません。

于 2015-08-11T08:41:17.470 に答える