I have a weird situation.
I need to manage a progress-augmented upload that needs to work with ancient.ie version 9.
Upload can be only done via submitting an iframe
POST, and we do that leveraging Flow js. During upload, an Ajax period request is issued to monitor the progress of the upload and fill the gauge on the UI.
@Scope("request")
@PreAuthorize("hasFunction('DMS')")
@Controller("/secure/admin/pages/dms/fileRepository")
@RequestMapping("/secure/admin/pages/dms/fileRepository")
public class FileRepositoryController extends BaseController
{
private final static Logger log = LogManager.getLogger();
@Autowired
private FileRepositoryManager fileRepositoryManager;
@Autowired
private ApplicationEventMulticaster eventDispatcher;
@RequestMapping(value = "/uploadProgress",
method =
{
RequestMethod.POST,
RequestMethod.GET
})
public PhoenixResponse uploadProgress(HttpSession session)
{
UploadInfo info = (UploadInfo) session.getAttribute(UploadInfo.SESSION_KEY);
if (info == null)
{
log.warn("Upload info not found in session");
return info().withSingleton(new UploadInfo());
}
PhoenixResponse res;
switch (info.getStatus())
{
case DONE:
{
session.removeAttribute(UploadInfo.SESSION_KEY);
res = success().withAlert("Upload OK", DEFAULT_ALERT_TIMEOUT);
break;
}
case PROGRESS:
case START:
case PROCESSING:
{
res = info();
break;
}
case ERROR:
{
res = error().withAlert("Errore upload");
break;
}
default:
throw new RuntimeException();
}
res = res.withSingleton(info)
.withResponseCode(info.getStatus()
.name());
return res;
}
@RequestMapping(path = "/uploadIframe",
consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
produces = MediaType.TEXT_HTML_VALUE)
public final @ResponseBody ResponseEntity<Void> uploadIframe(@RequestParam("file") MultipartFile file, HttpSession session)
{
upload(file, session); //Redirect to Ajax-ready method
return new ResponseEntity<>(HttpStatus.OK);
}
@RequestMapping(value = "/upload",
method = RequestMethod.POST,
consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public final PhoenixResponse upload(@RequestParam("file") MultipartFile file, HttpSession session) //Requires modern browser
{
UploadInfo info = (UploadInfo) session.getAttribute(UploadInfo.SESSION_KEY);
log.debug("Upload request received");
FileUploadDTO result;
if (file != null && !file.isEmpty())
{
String uploadFileName = IOUtils.getFileSafeName(file.getOriginalFilename());
log.debug("upload file: " + uploadFileName + " user: " + getUsername());
try
{
FileDescriptor fd;
try (InputStream is = file.getInputStream())
{
fd = fileRepositoryManager.store(is, uploadFileName, AdminModule.ID, getUsername());
}
result = new FileUploadDTO(fd.getName(), fd.getLength(), fd.getMimeType(), fd.getId());
eventDispatcher.multicastEvent(new FileUploadEvent(this, fd));
}
catch (IOException | RuntimeException ex)
{
info.setStatus(UploadState.ERROR);
log.error("Error uploading file", ex);
return error().withAlert(ex.getMessage());
}
}
else
return error();
if (info != null)
info.setStatus(UploadState.DONE);
return info().withSingleton(result);
}
}
Explanation: we have two upload methods. One is Ajax-ready and the other responds on POST requests. In fact the uplodaIframe
method returns a classic 200
empty page. But since the code is the same it just redirects the call to the Ajax-ready method, which return an unused response object
When invoking /uploadProgress
, though it doesn't use any @Autowired
bean, all autowires are set.
When invoking /uploadIframe
all beans are null despite there no required=false
on their autowires
I also found an interesting difference in the stack trace:
/uploadProgress
FileRepositoryController.uploadProgress(HttpSession) line: 106
FileRepositoryController$$FastClassByCGLIB$$7ccffed3.invoke(int, Object, Object[]) line: not available
MethodProxy.invoke(Object, Object[]) line: 204
CglibAopProxy$CglibMethodInvocation.invokeJoinpoint() line: 720
CglibAopProxy$CglibMethodInvocation(ReflectiveMethodInvocation).proceed() line: 157
MethodSecurityInterceptor.invoke(MethodInvocation) line: 68
CglibAopProxy$CglibMethodInvocation(ReflectiveMethodInvocation).proceed() line: 179
CglibAopProxy$DynamicAdvisedInterceptor.intercept(Object, Method, Object[], MethodProxy) line: 655
FileRepositoryController$$EnhancerBySpringCGLIB$$8768d018_2.uploadProgress(HttpSession) line: not available
GeneratedMethodAccessor1992.invoke(Object, Object[]) line: not available
Method.invoke(Object, Object...) line: 606
/uploadIframe
FileRepositoryController$$EnhancerBySpringCGLIB$$8768d018_2(FileRepositoryController).upload(MultipartFile, HttpSession) line: 144
FileRepositoryController$$EnhancerBySpringCGLIB$$8768d018_2(FileRepositoryController).uploadIframe(MultipartFile, HttpSession) line: 118
GeneratedMethodAccessor1993.invoke(Object, Object[]) line: not available
Method.invoke(Object, Object...) line: 606
I didn't exactly understand why, but the problem was related to the final
modifier of the two method.
Removing final
had the beans autowired correctly. Kudos to @M.Deinum
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.