我在我的web.xml中打开了Jersey JSON POJOMappingFeature,如下所示,将POJO转换为JSON :( / p>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
我在其中一个控制文件上传的控制器中有一个方法。它需要多部分表单数据,从表单中提取文件输入字段,将其转换为InputStream并将文件保存到磁盘:
@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces("application/json")
public FileMetaData uploadFiles(FormDataMultiPart formDataMultiPart) {
return new FileUploadHandler(SERVER_FILE_UPLOAD_LOCATION).upload(formDataMultiPart);
}
public FileMetaData upload(FormDataMultiPart formDataMultiPart) {
FormDataBodyPart formFile = formDataMultiPart.getField("files");
ContentDisposition contentDisposition = formFile.getContentDisposition();
return saveFile(formFile.getValueAs(InputStream.class), contentDisposition.getFileName(), formFile.getMediaType().toString());
}
这适用于所有文件格式,除非我尝试上传JSON文件时,formFile.getValueAs(InputStream.class)抛出一个错误,抱怨String无法转换为InputStream。我假设这是因为Jersey自动将JSON文件转换为字符串对象。 那么我怎样才能防止泽西为这个方法或控制器做这个呢?我的要求是我需要将json文件保存为文件本身。
我已经尝试过对此进行了大量搜索,但我最终得到的是有关如何启用POJOMapping而不是有选择地禁用POJOMapping的文档。任何帮助都将非常感谢!
更新: 我的自定义MessageBodyReader如下所示:
public class JSONMessageBodyReader implements MessageBodyReader<Object> {
private static final Logger log = LoggerFactory.getLogger(JSONMessageBodyReader.class);
@Override
public boolean isReadable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
// return true;
return mediaType.isCompatible(MediaType.APPLICATION_JSON_TYPE)
|| mediaType.isCompatible(MediaType.APPLICATION_OCTET_STREAM_TYPE);
|| mediaType.isCompatible(MediaType.TEXT_HTML_TYPE);
}
@Override
public Object readFrom(Class<Object> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
throws IOException, WebApplicationException {
if (log.isTraceEnabled()) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] chunk = new byte[256];
int read = -1;
while ((read = entityStream.read(chunk)) != -1) {
baos.write(chunk, 0, read);
}
chunk = baos.toByteArray();
String entity = new String(chunk);
log.trace("the entity: " + entity);
return ObjectMapperFactory.getInstance().readValue(chunk, 0, chunk.length, type);
}
return ObjectMapperFactory.getInstance().readValue(entityStream, type);
}
}
答案 0 :(得分:1)
我最终通过使用较低级别的HttpServletRequest而不是Jersey的FormDataParams处理上传的文件来解决我的要求,如下所示:
@POST
@Path("/upload")
@Consumes("multipart/form-data")
@Produces("application/json")
public FileMetaData uploadFiles(@Context ServletContext servletContext, @Context HttpServletRequest request) {
return fileUploadHandler.upload(request, servletContext);
}
public FileMetaData upload(HttpServletRequest request, ServletContext servletContext) {
FileMetaData fileMetaData = null;
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (isMultipart) {
LOGGER.info("About to save file on the server : {}", this.SERVER_UPLOAD_DIRECTORY);
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
diskFileItemFactory.setRepository(repository);
ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
try {
List<FileItem> files = servletFileUpload.parseRequest(request);
Iterator<FileItem> iter = files.iterator();
while(iter.hasNext()) {
FileItem fileItem = iter.next();
String fileName = fileItem.getName();
if (fileName != null) {
fileName = FilenameUtils.getName(fileName);
}
String fileUploadDirectory = this.SERVER_UPLOAD_DIRECTORY;
File uploadDirectory = new File(fileUploadDirectory);
if(!uploadDirectory.exists()) {
uploadDirectory.mkdir();
LOGGER.info("creating directory {}", uploadDirectory.getAbsolutePath());
}
String fileUploadPath = fileUploadDirectory + File.separator + fileName;
File fileToStore = new File(fileUploadPath);
LOGGER.info("saved file {} on server", fileName);
fileItem.write(fileToStore);
long fileSize = fileToStore.length();
String size = (fileSize > 1024) ? (fileSize/1024) + "Kb" : fileSize + "b";
fileMetaData = new FileMetaData(fileName, size, true);
}
} catch (Exception e) {
LOGGER.warn("error occurred while saving file to server : {}", e.getStackTrace());
e.printStackTrace();
}
}
else {
LOGGER.info("No files to upload in request");
}
return fileMetaData;
}
这个解决方案对我来说非常合适,尽管我觉得这对我原来的问题来说是一种黑客攻击。如果这个解决方案能够帮助其他人,那将会让我感到高兴。 但有人必须提供一种纯粹的泽西方式来解决这个问题而不涉及HttpServletRequest我会非常乐意尝试一下。 谢谢!