1

Goal: build a servlet so that when I type http://xxx.com/servpage?a.mp3 in browser, I can instantaneously start the playing of this mp3 file. Previously if I put the file on goDaddy as a static file, I can do that. My software can play it right away.

Using Servlet, I can ignore what is after ?, just want this page to return the mp3 dynamically (because in the future I may return any other files). What I got is a long wait (>20 seconds), and then got the player to play it.

I followed some examples, and noticed "attachment" in the example. However, if I remove it, the mp3 won't got played even. I am usign Google App Engine though, but just use the input/outputstream to return the http request. Anyone can help?

public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException ,IOException {
    res.setContentType("audio/mpeg3");
    OutputStream os = res.getOutputStream();
    res.setHeader("Content-Disposition", "attachment; filename="" + "a.mp3";");
    res.setContentLength(1000000);
    FileService fileService = FileServiceFactory.getFileService();
    boolean lockForRead = false;
    String filename =  "/gs/" + BUCKETNAME + "/" + FILENAME;
    AppEngineFile readableFile = new AppEngineFile(filename);

    try{
        FileReadChannel readChannel = fileService.openReadChannel(readableFile, lockForRead);
        InputStream is = Channels.newInputStream(readChannel);

        int BUFF_SIZE = 1024;
        byte[] buffer = new byte[BUFF_SIZE];
        try {
            do {
                int byteCount = is.read(buffer);
                if (byteCount == -1)
                    break;
                os.write(buffer, 0, byteCount);
                os.flush();
            } while (true);
        } catch (Exception excp) {
        } finally {
            os.close();
            is.close();
        }
        readChannel.close();
    } catch(Exception e){
    }
}
Hai Bi
  • 1,173
  • 1
  • 11
  • 21

1 Answers1

2

Few notes:

  1. You are not doing "streaming". Just a plain file download.

  2. To do blob (file) serving, you do not need to read the blob from BlobStore as you do with AppEngineFile. Just serve it directly with blobstoreService.serve(blobKey). See Serving a Blob for an example.

  3. You can get the BlobKey needed in 2. via fileService.getBlobKey(readableFile).

Update:

Just realized you are using Google Cloud Storage, not BlobStore.

In GS, if ACLs are properly set, files are publicly visible via: http://commondatastorage.googleapis.com/BUCKETNAME/FILENAME

Since you are not doing any authentication, you could publicly share the file on GS and then in your servlet just do a 301 redirect to public URL of the file.

Community
  • 1
  • 1
Peter Knego
  • 79,991
  • 11
  • 123
  • 154
  • Thanks, Peter. I was trying to have a java webstart application to access my file secretly so that the server will not be abused in any way. To do this, I will record the user's ip address and initiate sessions. I don't think just redirect to google cloud storage can do that. Also, I don't want the users be bothered with the java pop up window saying that the JavaWS is trying to access a file not from original web server. I realized that GAE doesn't send anything before the doGet returns and only allows 1 minute or processing. So I might need to break up the files to ranges or use blob. – Hai Bi Feb 29 '12 at 01:05
  • Good suggestion, Peter, just tried the blob. Looks like blob can serve the file as if the server is pushing before the file is totally loaded. And I can tell you very likely that it looks like the web server is pushing the data using another thread so my client can play music right away while still downloading. So you basically saved my day. Appreciated! – Hai Bi Feb 29 '12 at 02:18