Android Studio How to Upload Music in S3
Read Time: 22 mins Languages:
Amazon S3 is a corking style to store files, but learning how to integrate information technology into your website can be a challenge. In this commodity, you will learn how to integrate Amazon S3 and Crimson on Runway through the construction of a simple music streaming application.
What is it and How does information technology Work?
Amazon S3 is "storage for the Internet"
Every bit Amazon'south website puts information technology, Amazon S3 is "storage for the Cyberspace". Non simply is information technology inexpensive, information technology is also a fast and reliable. It'southward a corking way to serve content on your website, including images, videos, or pretty much anything that you want. Amazon S3 doesn't work exactly like the storage on your computer, and then hither are a few things that you should know:
- With Amazon S3, folders are chosen "buckets" and files are called "objects".
- Buckets on the top-level are used to determine the URL to access your data, so you can only employ names that haven't already been taken. For example, if someone already created a height-level bucket with the name "videos", you can't use that proper name.
- It is a good idea to accept one tiptop-level bucket with the name of your website, and use sub-levels of buckets to dissever files into dissimilar sections, such equally images, videos, or music.
Before We Begin...
Before yous go along with this tutorial, there are a few key things that should be in identify:
- The Carmine interpreter and RubyGems installed on your calculator, along with the Rails precious stone
- Knowledge of (or at to the lowest degree have access to) your Access Key ID and Secret Access Fundamental for Amazon S3
- A bones understanding of Ruby on Runway
What Nosotros'll exist Edifice
The final product of this tutorial is a unproblematic music streaming and downloading awarding. In this application, the user will be able to do the post-obit:
- View a list of all of the music currently uploaded and upload music themselves
- Download the music in a multifariousness of means, including streaming it with HTML5 audio, downloading it via HTTP, or downloading it via a .torrent file
By the time that this application is completed, you will take learned all of the major topics that you need to know virtually using Amazon S3 in your Ruby on Rails application.
Let's Get Started!
The aws-s3 jewel allows you to interact with the Amazon S3 service in your application.
The first affair to exercise is to install the aws-s3
ruby gem. The gem allows you to collaborate with the Amazon S3 service in your application. To do this, if you are on Windows, just run the command:
precious stone install aws-s3
After that is installed, generate our Rails application with the post-obit command:
rails new mp3app
The terminal step to get your application started is to go into the mp3app/public directory and delete the file chosen "alphabetize.html". Once that is completed, your awarding is ready to start interacting with Amazon S3!
Logging into Amazon S3
Your Access Key ID and Secret Access Central permit you to connect to Amazon S3.
In social club for us to interact with Amazon S3, we need to tell our application how to log into Amazon S3. This is where your Access Key ID and Undercover Admission Key come in handy. Your Admission Key ID and Clandestine Access Central allow you to connect to Amazon S3. But kickoff, nosotros need to tell our awarding that nosotros are using the aws-s3
gem. We do this in the Gemfile
:
jewel 'aws-s3', :require => 'aws/s3'
In order to actually let our application use that gem, yous'll need to type in command bundle install
. Now that it is working, we need to tell our application how to log into Amazon S3. We also do that in the config/application.rb
file, on a new line inside the Awarding class:
AWS::S3::Base.establish_connection!( :access_key_id => 'Put your Access Key ID here', :secret_access_key => 'Put your Hugger-mugger Access Key hither' )
This code tells our application to create a connection to Amazon S3 as before long every bit the awarding is started (the awarding.rb
file loads when your application starts up). One final affair that needs to be added to the application file is a constant with the value of the bucket that we will be using. The reason for doing this is that if we ever need to change which bucket we are using, information technology but needs to be updated in this one location. It should look something similar this:
BUCKET='s3tutorialmusic'
For this tutorial, I decided to proper name the bucket s3tutorialmusic
, but you should replace that with whatever bucket you lot have on your account. In the end, your file should look something like this (just with your ain login data):
crave File.expand_path('../boot', __FILE__) crave 'rails/all' Bundler.require(:default, Rails.env) if defined?(Bundler) module Mp3app grade Application < Rails::Application config.encoding = "utf-8" config.filter_parameters += [:password] AWS::S3::Base.establish_connection!( :access_key_id => 'Put your Access Central ID Here', :secret_access_key => 'Put your Secred Access Key here' ) Saucepan = 's3tutorialmusic' end end
Generating the Controller
Now we can finally brainstorm working on making our application really display something in the browser. To start, permit's generate the controller and views that we volition need. In total, we volition generate iii deportment for our controller (which we volition phone call songs): index, upload
and delete
.
- The index activeness is going to exist our main page.
- The upload activity is for uploading new music to Amazon S3, so it doesn't need a view.
- Finally, the delete action won't have a view, and will be responsible for deleting music.
In the end, the just view that nosotros will need for this application is the alphabetize view, considering information technology will human action every bit a fundamental control panel for every action that you can do. Now, we'll combine all that into 1 nice command line argument:
rails g controller Songs index upload delete
Once that has finished running, become ahead and delete the views generated for upload
and delete
, because they won't be used. Let's move on to writing the code for the index action!
Working on the Alphabetize Action
In the index activeness, the finished production will allow users to upload new music and delete existing music. There isn't anything that needs to be done in this activeness's controller file for uploading new music, but we do need a list of current songs in order to permit users delete them.
Outset, nosotros demand to get an object that refers to our music saucepan (remember that the name of that saucepan is stored in the constant Bucket). Here is how nosotros exercise that:
AWS::S3::Bucket.observe(BUCKET)
In order for us to use the methods bachelor in the aws-s3
precious stone, nosotros demand to tell the Ruby interpreter that we desire to look for the functions in the AWS::S3
namespace, which is why that is function of the method phone call. The Saucepan
grade contains all the methods related to manipulating buckets. Finally, the observe
method accepts 1 parameter, the name of the bucket, and returns an object that refers to that saucepan. At present that nosotros have the bucket, let'southward go all of its objects by doing this:
AWS::S3::Saucepan.find(Saucepan).objects
The objects
method returns a hash with the names of all of the objects in that saucepan. Finally, we need to store the result of that method call into an case variable and so that we can employ information technology in our view. In the end, this is what the index activeness will look like:
def index @songs = AWS::S3::Saucepan.find(Bucket).objects end
Continuing with the Index View
Now we need to make the view for the user to upload and delete music. Let's start with the later and create an unordered list of all of the objects currently uploaded, with a link to delete that object. We can exercise that similar so:
<ul> <% @songs.each practise |vocal| %> <li><%= song.primal %> - <%= link_to "Delete", "songs/delete/?song=" + vocal.fundamental, :confirm => 'Are you sure yous want to delete ' + vocal.cardinal + '?' %></li> <% stop %> </ul>
- Commencement, nosotros create an unordered list.
- Then, nosotros loop through all of the songs in the
@songs
variable by using the each method. - For each vocal, we create a list particular, and construct the text that will appear for each item. The first office is the songs key, considering each song is a hash, and the key for that hash is the name of the song.
- So, we put a link to the delete activeness, where the song tin exist deleted. For the url, we utilise a query string at the end to tell the delete activity which song needs to be deleted.
- Finally, we accept a confirmation message to warn the user before they actually delete the song.
if (params[:song]) AWS::S3::S3Object.find(params[:song], BUCKET).delete redirect_to root_path else render :text => "No song was constitute to delete!" end
- Start, we check to make sure that the vocal paramter was specified.
- If information technology was, then we use the find method to get the object representing that vocal.
- Finally, we use the delete method to delete it from Amazon S3.
- Later on, nosotros need to redirect the user to a new page because the delete action has no view. Nevertheless, if the song parameter was never specified, nosotros just render the text "No song was plant to delete!".
Letting the User Upload Music
Now, we need to actually let the user upload music, considering that was i of the core pieces of functionality for this application. First, we create a simple course that lets the user choose a file to upload. We can practice that similar so:
<h2>Upload a new MP3:</h2> <%= form_tag upload_path, :method => "post", :multipart => true practise %> <%= file_field_tag "mp3file" %> <%= submit_tag "Upload" %> <% cease %>
Nosotros create a form that submits to the upload action, which is the activity that really performs the upload to Amazon S3. We apply post and multipart because we are submitting files. Other than that, this form is very simple and easy to sympathize, so now we tin can move onto implementing the controller portion of this action.
Submitting the File to Amazon S3
We need to take the file that was submitted and create a new S3 object for it, which will be performed in the upload activity. We can practise that with this line of lawmaking:
AWS::S3::S3Object.store(sanitize_filename(params[:mp3file].original_filename), params[:mp3file].read, Bucket, :admission => :public_read)
There is a lot going on in this one line of code, and then I volition explain each part individually.
As usual, we access the AWS::S3::S3Object
in social club to interact with objects on Amazon S3.
Nosotros use the store
command to actually upload files to S3. The start parameter specifies what to call the file. Nosotros employ the original_filename
parameter of the uploaded file for this and then that the name stays the same. Equally for the sanitize_filename
method, that will exist explained in the next paragraph. The second parameter is the bodily file information, which is obtained from calling the read method on the uploaded file. The third parameter specifies the bucket to employ, and the fourth determines who can access the file. Because we want everyone to exist able to read the file (which includes downloading), we specify the admission as :public_read.
The sanitize_filename
method is a method that has been used by many people and plugins, such equally attachment_fu
, and information technology is used to solve a trouble with Cyberspace Explorer (shocking, isn't it?). Instead of just giving u.s.a. the name of the file when we phone call the original_filename method, IE returns the whole path to the file; for example, if the file we wanted to upload was chosen mysong.mp3
, it would instead give the states C:\rails\mp3app\mysong.mp3
when we call original_filename
. We can gear up this past adding the following code to the end of the controller:
private def sanitize_filename(file_name) just_filename = File.basename(file_name) just_filename.sub(/[^\w\.\-]/,'_') end
Our final step in completing the upload action is to add together some error checking and routes. The way that you lot do error checking in ruby is with a brainstorm...rescue...stop
statement. Many things could go wrong when uploading a file, then having error checking will prevent the user from seeing an mistake message that Rails would automatically generate. Hither is the modified version of the upload action:
def upload begin AWS::S3::S3Object.store(sanitize_filename(params[:mp3file].original_filename), params[:mp3file].read, BUCKET, :access => :public_read) redirect_to root_path rescue render :text => "Couldn't complete the upload" end terminate
If an error occurs, nosotros just return some text telling that to the user. Fifty-fifty though the user still sees an fault message, it is better than a huge listing of code that would announced in an mistake message generated by Rails.
Routing our Application
You may have noticed that throughout the code that we have written so far, there have been many times where something similar upload_path
has been used in place of specifying a controller and activity. We tin can exercise this considering of a file called routes.rb. This tells our application what URL's tin can be accessed in our application. We likewise give names to certain paths to brand it easier to update our code. Here is how you can proper noun the paths that our Mp3app volition use:
lucifer "songs/upload", :as => "upload" lucifer "songs/delete", :every bit => "delete" root :to => "songs#index"
The match method specifies a path, like songs/upload
, and give information technology a name, upload_path
. That name is specified using :as => "name"
as the second parameter to the lucifer method. Finally, the root method specifies what activity will be the root action, which acts like to alphabetize.html in a static HTML based website.
The Completed Upload Action
Now, we are done implementing the functionality of the upload activity. Here is the final lawmaking for the songs_controller.rb
file and so far:
class SongsController < ApplicationController def index @songs = AWS::S3::Bucket.find(Bucket).objects end def upload begin AWS::S3::S3Object.store(sanitize_filename(params[:mp3file].original_filename), params[:mp3file].read, Bucket, :access => :public_read) redirect_to root_path rescue render :text => "Couldn't complete the upload" end terminate def delete if (params[:vocal]) AWS::S3::S3Object.notice(params[:song], BUCKET).delete redirect_to root_path else render :text => "No vocal was establish to delete!" end end private def sanitize_filename(file_name) just_filename = File.basename(file_name) just_filename.sub(/[^\w\.\-]/,'_') end stop
And here is what the application looks like and then far when viewed in the browser.
Downloading the Music
So far, our application has come a long style. The user tin now upload music, view a listing of currently uploaded music, and delete whatever existing music. Now, we have one last piece of core functionality to implement. That is letting the user actually download this music. Equally specified in the start of this tutorial, the user can exercise that in three means:
- stream information technology with HTML5 Audio,
- download information technology via HTTP, and
- download it using a torrent file.
Right at present, the listing of music is only displayed using an unordered list. However, because we are going to cease up adding an additional 3 links to the end of each line (one for each download method), it is more feasible to utilize a table to organize the listing. Let's modify the index view to reverberate this alter:
<h2>Download and Delete Existing MP3's</h2> <tabular array> <% @songs.each practice |song| %> <tr> <td><%= song.key %></td> <td><%= link_to "Delete", "songs/delete/?vocal=" + vocal.key, :confirm => 'Are you certain you want to delete ' + song.key + '?' %></td> </tr> <% end %> </table>
- First, we update the header to reflect that we can also download the music.
- 2d, we change the unordered listing to a table, and put the proper noun of the vocal and the download link on their own <td>.
Now nosotros are ready to add the code to let the user download music. Let's start with downloading via HTTP, because it is the easiest one to implement.
Downloading via HTTP
To download via HTTP, we just demand to add a new <td> to our table with a link to the .mp3 file. The aws-s3 gem has built in methods that let us generate the url for a file. However, the all-time practise is to put any "helping methods" similar these in the helper file for that controller. Because we are using these methods throughout the whole application (especially if you determine to extend this application on your own), the helper methods volition be placed in the application_helper.rb file
. Here is how you lot go the URL:
def download_url_for(song_key) AWS::S3::S3Object.url_for(song_key, BUCKET, :authenticated => false) end
This method simply accepts i parameter, which is the name of the song. To help the states recall that the name of the song is accessed by vocal.central, nosotros call the parameter song_key
. Equally usual, nosotros access the AWS::S3::S3Object
class to interact with Amazon S3 objects. The url_for
method takes two parameters, with the tertiary being optional.
- The outset is the name of the file you are looking for.
- The second is the proper name of the bucket where the file is located.
- Finally, the third parameter is used to give us a URL that won't expire. If we didn't specify
:authenticated => fake
, the URL's would all expire in v minutes (by default).
<td><%= link_to "Download", download_url_for(song.fundamental) %></td>
This <td>
goes in between the proper noun of the song and the delete link (but that is personal preference, so you can have the links in any order y'all choose).
Downloading via Chip Torrent
Downloading files from Amazon S3 via Bit Torrent is very similar to downloading via HTTP. In fact, the only difference between the two download URL'due south is that the torrent one has ?torrent at the stop of it. Therefore, our helper method to generate the torrent url will just add ?torrent to the finish of the HTTP url. Here is how y'all would practice that:
def torrent_url_for(song_key) download_url_for(song_key) + "?torrent" end
Now, we simply need to add another <td> to our table:
<td><%= link_to "Torrent", torrent_url_for(song.key) %></td>
Streaming with HTML5 Sound
Streaming the songs through HTML5 audio is a little more difficult than just downloading the song, and then let's start with the like shooting fish in a barrel part: the <td>
for it. Yet, there are going to exist some differences from the links we added for HTTP and Bit Torrent.
- First, we need to have a fashion to identify this link in guild to add the <sound> tag to the page, so we volition give it a class of html5.
- 2d, we demand a way to know the source of the mp3 to use for the
<source>
tag, so nosotros volition just give information technology the same url every bit the HTTP download. This will also serve as a fallback for browsers with javascript disabled, considering we will use javascript to add the<audio>
tag to the page.
Here is the lawmaking for generating the link:
<td><%= link_to "HTML5 Audio", download_url_for(song.key), :class => "html5" %></td>
At present we need to work on the javascript to add the sound tag to the folio when this link is clicked. To do this, we will utilize a technique similar to the technique that Jeffrey Fashion uses in his tutorial, The HTML five Audio Element. The showtime step is to add a few things to our view files. In our layout/application.html.erb
file, we need to include the latest version of jQuery, because that is the javascript library nosotros will be using. Hither is the code to add right before the starting time javascript include line:
<%= javascript_include_tag "https://ajax.googleapis.com/ajax/libs/jquery/1.four.three/jquery.min.js" %>
And so, change the starting time parameter for the original include tag from :defaults to application.js
, considering that is where we will exist storing our javascript lawmaking, and the other default JavaScript files aren't necessary. Adjacent, we need to add together a section to our index.html.erb view to put the audio tag in. At the top of that view, we demand to put the post-obit lawmaking:
<h2>Heed to a MP3 with HTML5 Audio</h2> <section id="audio"> </section>
Following with the HTML5 theme, we utilise a section tag instead of a div to create our audio section.
We get a reference to the sound section and cache it in a variable, which is considered a best practice. Next, nosotros need to add a click event handler to our links with the html 5 class. When that event handler goes off, we need to exercise a few things:
- First, we demand to make a new audio tag and give it some attributes like controls.
- And so, we need to add the source tag to it so it actually knows what to play.
- Finally, we need to replace the HTML in the audio section with the new sound tag, and render false then that the normal action of the link doesn't get through, which would be downloading the song. Here is how y'all tin put that all together:
$(document).ready(function() { var audioSection = $('section#audio'); $('a.html5').click(role() { var sound = $('<audio>', { controls : 'controls' }); var url = $(this).attr('href'); $('<source>').attr('src', url).appendTo(audio); audioSection.html(audio); render false; }); });
Since this tutorial is nigh Cherry-red on Track, and not JavaScript, I won't get into detail explaining how this code works. Nevertheless, the code is fairly elementary, so it should be piece of cake for you to figure out. One affair that you should notation is that this will just work in browsers that back up HTML5 and back up mp3's equally valid sources for audio tags. For near browsers, the latest version will back up this HTML 5 lawmaking, but older browsers don't support this.
Completed Index View
Nosotros take finally completed all of the core functionality for this application. The user can upload, download, and delete mp3's in a diverseness of means, including HTML5 Audio, HTTP Downloads, and Flake Torrent. Here is what the index view should look like at this point:
<h2>Heed to a MP3 with HTML5 Audio</h2> <section id="audio"> </section> <h2>Upload a new MP3</h2> <%= form_tag upload_path, :method => "postal service", :multipart => true do %> <%= file_field_tag "mp3file" %> <%= submit_tag "Upload" %> <% finish %> <h2>Download and Delete Existing MP3'due south</h2> <tabular array> <% @songs.each do |song| %> <tr> <td><%= song.key %></td> <td><%= link_to "HTML5 Audio", download_url_for(song.central), :class => "html5" %></td> <td><%= link_to "Download", download_url_for(song.fundamental) %></td> <td><%= link_to "Torrent", torrent_url_for(song.key) %></td> <td><%= link_to "Delete", "songs/delete/?song=" + song.key, :confirm => 'Are you lot sure you desire to delete ' + song.central + '?' %></td> </tr> <% end %> </tabular array>
If you oasis't already, you should try running this code and trying information technology out for yourself. You can do this past running the command: track s
. Even though we have completed the core functionality for this application, in that location are nonetheless things that need to be done, such as styling the page. Let's do that now.
Styling the Application
The first thing to do is to wrap the folio in a container so that nosotros tin can center it. All we need to do is put a div with an id of container effectually the yield statement in the layout file and so that information technology looks something like this:
<div id="container"> <%= yield %> </div>
Side by side, we volition employ the styling from Ryan Bates gem, nifty_generators
, to give our application some basic styling. Here is the CSS that we will employ from that gem:
#container { width: 75%; margin: 0 auto; background-colour: #FFF; padding: 20px 40px; border: solid 1px black; margin-tiptop: 20px; } trunk { background-color: #4B7399; font-family: Verdana, Helvetica, Arial; font-size: 14px; } .clear { clear: both; elevation: 0; overflow: hidden; }
Now we volition work the index view. The first thing that we demand to do is split the page into iii sections. Those sections will exist a header, a main section, and a sidebar. At the top of the page, allow's add a uncomplicated header:
<header> <h1>My First Music Streaming Application</h1> </header>
Next, let's divide the page into a main region and a sidebar region. Our chief region will consist of the list of songs, while the sidebar volition contain the HTML5 audio and the upload form. Here is how we volition modify the code:
<div class="clear"></div> <section id="sidebar"> <h2>HTML5 Sound</h2> <section id="audio"> No vocal is currently playing. </department> <h2>Upload a Song</h2> <%= form_tag upload_path, :method => "post", :multipart => truthful do %> <%= file_field_tag "mp3file" %><br /> <%= submit_tag "Upload" %> <% stop %> </department> <section id="main"> <h2>Download/Delete Songs</h2> <table> <% @songs.each do |song| %> <tr> <td><%= song.key %></td> <td><%= link_to "HTML5 Sound", download_url_for(vocal.primal), :course => "html5" %></td> <td><%= link_to "Download", download_url_for(song.primal) %></td> <td><%= link_to "Torrent", torrent_url_for(song.key) %></td> <td><%= link_to "Delete", "songs/delete/?song=" + song.central, :confirm => 'Are you certain you desire to delete ' + song.key + '?' %></td> </tr> <% finish %> </table> </section> <div class="articulate"></div>
Since we volition exist using floats to blueprint this page, nosotros need to clear the floats before and after to make certain that the layout doesn't go messed upward. Now let's add the CSS to adjust the layout of those sections:
#sidebar { width: 30%; bladder: left; } #chief { width: seventy%; bladder: left; } a, a:visited { color: #00f; text-decoration: none; } a:hover { text-decoration: underline; } td { padding: 5px; }
The sidebar will be 30% of the folio, and the main department volition be 70% of the page. In addition, there is CSS to remove the underline from the links unless the mouse is hovering over it, and there is as well padding added to the <td> tags and then that it doesn't look and then cramped. In the end, that is really the only CSS we need to give the page a basic layout. Feel free to add as much styling to this application as you want on your own, because there are certainly means to brand this application look nicer.
Conclusion
Hopefully you now accept a expert understanding of how to interact with Amazon S3 from your Ruby on Rails application. With the aws-s3
precious stone, doing this is very easy, so adding it to an existing application will accept very little time. Experience costless to modify this application in any style you similar to see if you tin ameliorate it in any way. Remember to add together your ain Amazon S3 login information and bucket constant to the application.rb
file, otherwise the awarding won't start!
For those of you who are Ruby on Rails experts, I'k sure that you tin detect a way to optimize this application even more. In addition, it would be dandy to share any optimizations that you brand in the comments section so that readers can get fifty-fifty more than out of this tutorial.
Did you notice this post useful?
Source: https://code.tutsplus.com/articles/create-a-simple-music-streaming-app-with-ruby-on-rails--net-18437
0 Response to "Android Studio How to Upload Music in S3"
Post a Comment