【发布时间】:2013-01-14 23:00:37
【问题描述】:
我尝试将大图像上传/流式传输到 REST 控制器,该控制器获取文件并将其存储到数据库中。
@Controller
@RequestMapping("/api/member/picture")
public class MemberPictureResourceController {
@RequestMapping(value = "", method = RequestMethod.POST)
@ResponseStatus(HttpStatus.NO_CONTENT)
public void addMemberPictureResource(@RequestBody InputStream image) {
// Process and Store image in database
}
}
这是我试图实现的一个无效示例(当然,或者我猜 InputStream 不工作)。我想通过@RequestBody 流式传输/读取图像。
我到处搜索,但找不到一个很好的例子来实现这一点。大多数人似乎只问如何通过表单上传图像,但不使用 REST/RestTemplate 来做到这一点。有没有人可以帮助我解决这个问题?
感谢您对正确方向的任何提示。
亲切的问候, 克里斯
解决方案
在下面,我尝试在 Dirk 和 Gigadot 的输入之后发布对我有用的解决方案。目前我认为这两种解决方案都值得一看。首先,我尝试在 Dirk 的帮助下发布一个工作示例,然后我将尝试在 Gigadot 的帮助下创建一个。我将 Dirks 的答案标记为正确答案,因为我一直在明确询问如何通过 @RequestBody 上传文件。但我也很想测试 Gigadot 的解决方案,因为它可能更容易使用且更常见。
在以下示例中,我将文件存储在 MongoDB GridFS 中。
解决方案 1 - Dirks 推荐后的示例
控制器(注释中带有用于测试的 curl 命令):
/**
*
* @author charms
* curl -v -H "Content-Type:image/jpeg" -X PUT --data-binary @star.jpg http://localhost:8080/api/cardprovider/logo/12345
*/
@Controller
@RequestMapping("/api/cardprovider/logo/{cardprovider_id}")
public class CardproviderLogoResourceController {
@Resource(name = "cardproviderLogoService")
private CardproviderLogoService cardproviderLogoService;
@RequestMapping(value = "", method = RequestMethod.PUT)
@ResponseStatus(HttpStatus.NO_CONTENT)
public void addCardproviderLogo(@PathVariable("cardprovider_id") String cardprovider_id,
HttpEntity<byte[]> requestEntity) {
byte[] payload = requestEntity.getBody();
InputStream logo = new ByteArrayInputStream(payload);
HttpHeaders headers = requestEntity.getHeaders();
BasicDBObject metadata = new BasicDBObject();
metadata.put("cardproviderId", cardprovider_id);
metadata.put("contentType", headers.getContentType().toString());
metadata.put("dirShortcut", "cardproviderLogo");
metadata.put("filePath", "/resources/images/cardproviders/logos/");
cardproviderLogoService.create1(logo, metadata);
}
}
服务(未完成但作为测试工作):
@Service
public class CardproviderLogoService {
@Autowired
GridFsOperations gridOperation;
public Boolean create1(InputStream content, BasicDBObject metadata) {
Boolean save_state = false;
try {
gridOperation.store(content, "demo.jpg", metadata);
save_state = true;
} catch (Exception ex) {
Logger.getLogger(CardproviderLogoService.class.getName())
.log(Level.SEVERE, "Storage of Logo failed!", ex);
}
return save_state;
}
}
解决方案 2 - Gigadots 推荐后的示例
这在 Spring 手册中有描述: http://static.springsource.org/spring/docs/3.2.1.RELEASE/spring-framework-reference/html/mvc.html#mvc-multipart
这很简单,默认情况下还包含所有信息。我想我至少会为二进制上传选择这个解决方案。
感谢大家发帖和回答。非常感谢。
【问题讨论】:
-
post 方法应该使用多部分形式
-
感谢 gigadot,但我将使用 resttemplate 将文件解析到控制器,我想将它放在 requestbody 中。我不知道使用多部分是否真的符合休息标准。是吗?
-
感谢 gigadot。我会研究这个解决方案。你的意思是我应该使用具有流功能的 apache-commons-fileupload 来上传文件而不是 REST?我可以使用 RestTemplate 来解析文件吗?
-
我已将其发布为答案。我希望它可能会有所帮助。如果没有,您可以在 Google 上搜索“multipart spring mvc”。那里有很多示例,但如果您使用的是新版本的 spring,您可能想尝试最近的示例。
标签: spring rest spring-mvc