Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example analysis of ajax asynchronously uploading video with progress bar and extracting thumbnails

2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

What this article shares with you is an example analysis of ajax asynchronously uploading video with progress bar and extracting thumbnails. The editor thinks it is very practical, so I share it with you to learn. I hope you can get something after reading this article. Without saying much, follow the editor to have a look.

Recently, I am working on a project that integrates rich media functions. Video needs to be uploaded. Here I want to upload asynchronously, and have progress bar, response with status code, video link, thumbnail.

Server response

{"thumbnail": "/ slsxpt//upload/thumbnail/fdceefc.jpg", "success": true, "link": "/ slsxpt//upload/video/fdceefc.mp"}

And hope that my input file control will not be wrapped with form tags. The reason is that form cannot be nested in form, and form tags still have a little default style in the browser, so you may have to write css again.

Used ajaxFileUpload to upload files asynchronously before. However, this thing has not been updated for a long time, and the code still has bug. Although it has been used successfully in the end, it always feels bad. And ajaxFileUpload does not directly add xhr2's progress event response, which is troublesome.

After looking for it on the Internet, I found that there are many ways.

For example, after the file is uploaded, put the upload progress into session and poll the server session. But I always think there is something wrong with this method. I think the progress seen by this method should be the progress of my server application code (that is, action) copying files from the server's temporary directory, because all requests should be submitted to the server software first, that is, tomcat,tomcat encapsulates objects such as session,request, and the files should actually be received by it. That means the file is actually uploaded before my action code executes.

Later I found a better way to use the ajaxSubmit method of the jquery.form.js plug-in. This method is submitted as a form, that is, $.fn.ajaxSubmit.: $(form selector). AjaxSubmit ({}). The advantage of this api is that it has handled the progress time of xhr2. You can pass a function of uploadProgress when you call it, and you can get the progress in function. And it doesn't matter if you don't want input file to be wrapped by form, createElement should work in the code. However, I didn't succeed in this method because I made a small mistake, which is a pity.

AjaxSubmit source code

Finally, the $.ajax method is used to do it. $. Ajax does not need to be associated with form, which is a bit like a static method. The only regret is that there is no response to progress in the $.ajax options. However, it has a parameter of xhr, that is, you can customize xhr, and you can add progress event handlers through xhr for so long. When we take a look at the handling of progress events in the ajaxSubmit method, it suddenly becomes clear.

Then I can also add the progress event handler to the $. Ajax method. In order to extract the operation on dom from the upload business, I decided to write in the form of a plug-in. Here is the code for the plug-in

; (function ($) {var defaults = {uploadProgress: null, beforeSend: null, success: null,}, setting = {}; var upload = function ($this) {$this.parent (). On ('change',$this,function (event) {/ / var $this = $(event.target), var formData = new FormData (), target = event.target | | event.srcElement / / $.each (target.files, function (key, value) / / {/ / console.log (key); / / formData.append (key, value); / /}); formData.append ('file',target.files []); settings.fileType & & formData.append (' fileType',settings.fileType) $.ajax ({url: $this.data ('url'), type: "POST", data: formData, dataType:' json', processData: false, contentType: false, cache: false, beforeSend: function () {/ / console.log ('start') If (settings.beforeSend) {settings.beforeSend ();}}, xhr: function () {var xhr = $.ajaxSettings.xhr () If (xhr.upload) {xhr.upload.addEventListener ('progress',function (event) {var total = event.total, position = event.loaded | | event.position, percent =; if (event.lengthComputable) {percent = Math.ceil (position / total *) } if (settings.uploadProgress) {settings.uploadProgress (event, position, total, percent);}}, false);} return xhr;}, success: function (data,status,jXhr) {if (settings.success) {settings.success (data) }, error: function (jXhr,status,error) {if (settings.error) {settings.error (jXhr,status,error);}; $.fn.uploadFile = function (options) {settings = $.extend ({}, defaults, options) / / File upload return this.each (function () {upload ($(this));});}}) ($| | jQuery)

Now I can use this api in my jsp page.

(function ($) {$(document) .ready (function () {var $progress = $('.uploadVideoProgress'), start = false; $('input.uploadInput.uploadVideo') .uploadFile ({beforeSend: function () {$progress.parent (). Show ()) }, uploadProgress: function (event, position, total, percent) {$progress.attr ('aria-valuenow',percent); $progress.width (percent+'%'); if (percent > =) {$progress.parent (). Hide (); $progress.attr (' aria-valuenow',); $progress.width (+'%') }, success: function (data) {if (data.success) {setTimeout (function () {$('# thumbnail'). Attr ('src',data.thumbnail);},);}) }) (jQuery)

Here, the image is obtained after setting a timeout of 800ms in response to succes, because extracting the thumbnail is another process that has not yet finished extracting the thumbnail when the possible response is completed.

Let's see the effect.

Extract thumbnail image

The following part is the server processing upload, and the video extraction thumbnail below is the action processing code

Package org.lyh.app.actions; import org.apache.commons.io.FileUtils; import org.apache.struts.ServletActionContext; import org.lyh.app.base.BaseAction; import org.lyh.library.SiteHelpers; import org.lyh.library.VideoUtils; import java.io.File; import java.io.IOException; import java.security.KeyStore; import java.util.HashMap; import java.util.Map; / * Created by admin on / /. * / public class UploadAction extends BaseAction {private String saveBasePath; private String imagePath; private String videoPath; private String audioPath; private String thumbnailPath; private File file; private String fileFileName; private String fileContentType; / / omit setter getter method public String video () {Map dataJson = new HashMap (); System.out.println (file); System.out.println (fileFileName); System.out.println (fileContentType); String fileExtend = fileFileName.substring (fileFileName.lastIndexOf (".")) String newFileName = SiteHelpers.md (fileFileName + file.getTotalSpace ()); String typeDir = "normal"; String thumbnailName = null,thumbnailFile = null; boolean needThumb = false,extractOk = false; if (fileContentType.contains ("video")) {typeDir = videoPath; / / extract thumbnail needThumb = true; thumbnailName = newFileName + ".jpg"; thumbnailFile = app.getRealPath (saveBasePath + thumbnailPath) + "/" + thumbnailName } String realPath = app.getRealPath (saveBasePath + typeDir); File saveFile = newFile (realPath, newFileName + fileExtend); / / there is a file with the same name, skip if (! saveFile.exists ()) {if (! saveFile.getParentFile (). Exists ()) {saveFile.getParentFile (). Mkdirs ();} try {FileUtils.copyFile (file, saveFile) If (needThumb) {extractOk = VideoUtils.extractThumbnail (saveFile, thumbnailFile); System.out.println ("thumbnail extracted successfully:" + extractOk);} dataJson.put ("success", true);} catch (IOException e) {System.out.println (e.getMessage ()); dataJson.put ("success", false) } else {dataJson.put ("success", true);} if ((Boolean) dataJson.get ("success")) {dataJson.put ("link", app.getContextPath () + "/" + saveBasePath + typeDir + "/" + newFileName + fileExtend); if (needThumb) {dataJson.put ("thumbnail", app.getContextPath () + "/" + saveBasePath + thumbnailPath + "/" + thumbnailName) }} this.responceJson (dataJson); return NONE;}}

Action configuration

/ upload / images / video / audio / thumbnail

Personally, I think that if the name and size of the file are exactly the same, the probability that they are a file is very high, so I take the file name and the file size to do the md5 operation, which should be able to avoid uploading the same file repeatedly.

FFmpeg is used when transcoding. You can download what you need here.

Package org.lyh.library; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; / * Created by admin on / /. * / public class VideoUtils {public static final String FFMPEG_EXECUTOR = "C:/Software/ffmpeg.exe"; public static final int THUMBNAIL_WIDTH =; public static final int THUMBNAIL_HEIGHT =; public static boolean extractThumbnail (File inputFile,String thumbnailOutput) {List command = new ArrayList (); File ffmpegExe = new File (FFMPEG_EXECUTOR); if (! ffmpegExe.exists ()) {System.out.println ("Transcoding tool does not exist"); return false } System.out.println (ffmpegExe.getAbsolutePath ()); System.out.println (inputFile.getAbsolutePath ()); command.add (ffmpegExe.getAbsolutePath ()); command.add ("- I"); command.add (inputFile.getAbsolutePath ()); command.add ("- y"); command.add ("- f"); command.add ("image"); command.add ("- ss"); command.add ("") Command.add ("- t"); command.add ("."); command.add ("- s"); command.add (THUMBNAIL_WIDTH+ "*" + THUMBNAIL_HEIGHT); command.add (thumbnailOutput); ProcessBuilder builder = new ProcessBuilder (); builder.command (command); builder.redirectErrorStream (true); try {long startTime = System.currentTimeMillis (); Process process = builder.start () System.out.println ("startup time" + (System.currentTimeMillis ()-startTime)); return true;} catch (IOException e) {e.printStackTrace (); return false;}

In addition, here is another process started by java, in my opinion, they should be unrelated to each other. After java starts ffmpeg.exe, it should come back and continue to execute the following code, so there is no need to set up a separate thread to extract the thumbnail. The test also found that it didn't take much time. The time of each long pass is not much different. Here are two uploads of the same file.

For the first time

The second time

There is not much difference in terms of user experience.

In addition, uploading large files here requires some configuration of tomcat and struct.

Modify the server.xml file under the conf directory under tomcat, and add an attribute maxPostSize= "0" to the Connector node to indicate that the upload size is not displayed.

In addition, modify the struts.xml add configuration. The value units here are bytes, which is about more than 300 mb.

The above is the example analysis of ajax asynchronously uploading video with progress bar and extracting thumbnails. The editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report