0

マルチパート フォーム データを Web クライアントから Spring MVC コントローラーにアップロードしようとしています。次のcurlコマンドの「Spring」実装を検索します。

curl -v -X POST -F "logo=@walmart.jpg" -F "id=12345" -F "name=Walmart" http://localhost:8080/api/cardprovider/logo

注意: 私は html フォームを介してフォームのアップロードを行っていません。これは私が達成したいことではありません。

今私の質問は:

  • この ブログで説明されているように、Apache Commons HttpClient を使用しますか?
  • または、これを行うのに役立つ「Spring」の種類の Magic ライブラリはありますか?

Spring ライブラリを使用して解決策を探すのに何日も費やしましたが、Spring マニュアルのすべての例は、html フォームのアップロードを参照しているか、基本的なテキストのみの非常に基本的で単純なものです。

Spring は私にとってかなり新しいものですが、内部には非常に多くの優れたライブラリがあるため、Spring の担当者がマルチパート データのアップロードをより簡単にするために考えたことがなかったら驚くでしょう (まるでそれがフォームから送信されます)。

上記の curl コマンドは、次のサーバー側コードで正常に機能しています。

コントローラ:

@Controller
@RequestMapping("/api/cardprovider/logo")
public class CardproviderLogoResourceController {

  @Resource(name = "cardproviderLogoService")
  private CardproviderLogoService cardproviderLogoService;

  /**
   * Used to upload a binary logo of a Cardprovider through a Multipart request. The  id is provided as form element.
   * <p/>
   * Example to upload a file using curl:
   * curl -v -X POST -F "image=@star.jpg" -F "id=12345" -F "name=Walmart" http://localhost:8080/api/cardprovider/logo
   * <p/>
   *
   * @param logo the Multipart request
   * @param id    the Cardprovider id
   * @param name  the Cardprovider name
   */
  @RequestMapping(value = "", method = RequestMethod.POST)
  @ResponseStatus(HttpStatus.NO_CONTENT)
  public void storeCardproviderLogo(@RequestParam(value = "logo", required = false) MultipartFile logo,
                                  @RequestParam(value = "name") String name,
                                  @RequestParam(value = "id") String id) throws IOException {

    cardproviderLogoService.storeLogo(logo, id, name);
  }
}

マルチパートリクエストをGridFSデータベースに格納するサービスクラスは次のとおりです。

サービス:

@Service
public class CardproviderLogoService {

  @Autowired
  GridFsOperations gridOperation;

  /**
   * Create the logo in MongoDB GridFS with the data returned from the Multipart
   * <p/>
   *
   * @param logo the MultipartFile content
   * @param id      the Cardprovider id
   * @param name    the Cardprovider name
   * @return true if the image can be saved in the database, else false
   */
  public Boolean storeLogo(MultipartFile logo, String id, String name) {
    Boolean save_state = false;

    BasicDBObject metadata = new BasicDBObject();
    metadata.put("cardproviderId", id);
    metadata.put("cardproviderName", name);
    metadata.put("contentType", logo.getContentType());
    metadata.put("fileName", createLogoFilename(name, logo.getOriginalFilename()));
    metadata.put("originalFilename", logo.getOriginalFilename());
    metadata.put("dirShortcut", "cardproviderLogo");
    metadata.put("filePath", "/resources/images/cardproviders/logos/");

    try {
        gridOperation.store(logo.getInputStream(),
                metadata.getString("fileName").toLowerCase().replace(" ", "-"),
                metadata);
        save_state = true;
    } catch (Exception ex) {
        Logger.getLogger(CardproviderLogoService.class.getName())
                .log(Level.SEVERE, "Storage of Logo failed!", ex);
    }

    return save_state;
}

/**
 * Creates the new filename before storing the file in MongoDB GridFS. The filename is created by taking the
 * name of the Cardprovider, lowercase the name and replace the whitespaces with dashes. At last the file
 * extension is added that was provided by the original filename.
 * <p/>
 *
 * @param name the Cardprovider name
 * @param originalFilename the original filename
 * @return the new filename as String
 */
private String createLogoFilename(String name, String originalFilename) {
    String cpName = name.toLowerCase().replace(" ", "-");

    String extension = "";
    int i = originalFilename.lastIndexOf('.');
    if (i > 0 && i < originalFilename.length() - 1) {
        extension = originalFilename.substring(i + 1).toLowerCase();
    }
    return cpName + "." + extension;
  }
}

助けてくれてありがとう、クリス

解決

次の方法で問題を解決できました。入力形式を取り、RestController への接続を構築してファイルを転送する HtmlController があります。

HtmlController のメソッドは次のとおりです。

@RequestMapping(value = "/add", method = RequestMethod.POST)
public String addCardprovider(
        @ModelAttribute("cardproviderAttribute") Cardprovider cardprovider,
        Model model) {

    // Prepare acceptable media type
    List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
    acceptableMediaTypes.add(MediaType.APPLICATION_XML);

    // Prepare header
    HttpHeaders headers = new HttpHeaders();
    headers.setAccept(acceptableMediaTypes);
    // Pass the new person and header
    HttpEntity<Cardprovider> entity = new HttpEntity<Cardprovider>(
            cardprovider, headers);

    // Send the request as POST
    try {
        // Save Cardprovider details
        ResponseEntity<Cardprovider> response = restTemplate.exchange(
                "http://localhost:8080/api/cardprovider", HttpMethod.POST,
                entity, Cardprovider.class);

        // Save Cardprovider logo
        String tempDir = System.getProperty("java.io.tmpdir");
        File file = new File(tempDir + "/" + cardprovider.getLogo().getOriginalFilename());
        cardprovider.getLogo().transferTo(file);

        MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
        parts.add("id", response.getBody().getId());
        parts.add("name", response.getBody().getName());
        parts.add("logo", new FileSystemResource(file));

        restTemplate.postForLocation("http://localhost:8080/api/cardprovider/logo", parts);

    } catch (Exception e) {
        e.printStackTrace();
    }

    // This will redirect to /web/cardprovider/getall
    return "redirect:/web/cardprovider/getall";
}
4

1 に答える 1

0

私が知っている春には何もありません。このようなタスクに Apache Commons HttpClient を使用することは、私のサークルでは一般的な方法です。

アップデート

もちろん、Spring はそれをサポートしています。申し訳ありませんが、最も明白なRestTemplateを見落としていました。

XML:

<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
 <property name="messageConverters">
  <list>
   <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
   <bean class="org.springframework.http.converter.FormHttpMessageConverter" />
  </list>
 </property>
</bean>

ジャワ:

MultiValueMap<String, Object> form = new LinkedMultiValueMap<String, Object>();
form.add("key", value);
...
form.add("file", new FileSystemResource(file));
restTemplate.postForLocation(url, form);
于 2013-02-07T23:12:02.470 に答える