Is there any way to generate temporary links for downloading file using spring web, security-oauth stack?
For example domain.com/document/ed3dk4kfjw34k43kd4k3cc
that works only on current session?
You can try to add Map<String, String>
to the session. After that you can store generated unique strings and file names into this map. Every time, when you need to load file by unique generated string, you'll find real file name by string and send it to client. Simple component for demonstration of idea:
@Component
@Scope(value = "session")
public class SessionFileMap {
private Map<String, String> fileMap = new HashMap<>();
public String getUniqueString(String fileName){
for(String uniqueName: fileMap.keySet()){
//check, if file already in map, return it
if(fileMap.get(uniqueName).equals(fileName)) return uniqueName;
}
//otherwise, create new
String uniqueName = generateUniqueName();
fileMap.put(uniqueName, fileName);
return uniqueName;
}
public String getFileName(String uniqueString){
if(fileMap.containsKey(uniqueString)){
return fileMap.get(uniqueString);
}
return null;
}
private String generateUniqueName() {
String uniqueString = //generation of unique string
return uniqueString;
}
}
Of course, you have to make this component scope session
. And there is good examples, how you can generate unique strings. Now example of usage of this component:
@Controller
@Scope(value = "session")
public class FileController {
@Autowired
private SessionFileMap fileMap;
@Autowired
private ApplicationContext context;
@RequestMapping("/file")
public String showLink(ModelMap model, HttpSession session){
String uniqueString = fileMap.getUniqueString("/filepath/filename.ext");
model.addAttribute("uniqueString", uniqueString);
return "file";
}
@RequestMapping("/download/{uniqueString}")
public void download(@PathVariable("uniqueString") String uniqueString,
HttpServletResponse response){
String fileName = fileMap.getFileName(uniqueString);
try{
Resource resource = context.getResource("file:"+fileName);
try (InputStream is = resource.getInputStream()) {
//prepare all headers for download ...
IOUtils.copy(is, response.getOutputStream());
response.flushBuffer();
}
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
Controller must have scope of session
as well as component. If you noted, I used IOUtils.copy()
from org.apache.commons
to copy stream, but you can do it as you prefer. In view, links will looks like following:
<html>
<head>
<title></title>
</head>
<body>
<a href="/download/${uniqueString}">Download</a>
</body>
</html>
This is just demonstration of basic idea. And all details are up to you.