我尝试将多部分表单数据从Web客户端上传到Spring MVC Controller。我搜索了一个" Spring"以下curl命令的实现:
curl -v -X POST -F "logo=@walmart.jpg" -F "id=12345" -F "name=Walmart" http://localhost:8080/api/cardprovider/logo
请注意:我没有在html表单上进行表单上传,这不是我想要实现的目标。
现在我的问题是:
我花了几天时间使用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);
}
}
这是我的服务类,它将Multipart请求存储到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;
}
}
感谢您的帮助和亲切的问候, 克里斯
解决方案
我可以通过以下方式解决问题。我有我的HtmlController,它接受表单Input并建立与RestController的连接以传输文件。
这是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";
}
答案 0 :(得分: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);